阅读 98

动态REM

这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战

em 和 rem

em 和 rem 都是众多长度单位的中的一种,MDN 给出的定义分别是

em是一个相对长度单位,这个单位表示元素的font-size的计算值。如果用在font-size属性本身,它会继承父元素的font-size。

1em == 自己的font-size的像素值

rem代表根元素的font-size大小(例如<html>元素的font-size)。当用在根元素的font-size上面时 ,它代表了它的初始值。

1rem == html的font-size的像素值

其他的长度单位还有px(像素)、vw(100vw == 视口宽度)、vh(100vh == 视口高度)等等。

注意:

  • chrome 默认 font-size 大小为 16px
  • chrome 默认最小字号为 12px(可在设置中更改),这意味着即使设置font-size < 12px,打开控制台查看计算出来的 font-size 依旧是 12px

移动端的特点

打开开发者工具切换到手机端,我们发现所有手机显示的界面都大同小异,不同的仅仅只是屏幕的大小(宽高)

机型大小
iPhone 4320 x 480
iPhone 5/SE320 x 568
iPhone 6/7/8375 x 667
iPhone 6/7/8 Plus414 x 736
iPhone X375 x 812

移动端适配方案

方案一:媒体查询

从上面可以看出,光是iPhone这一类手机就有如此多不同的宽高,更别说要适配所有手机了,显然这时候如果使用媒体查询来做适配不可取(那得写n多套样式)

方案二:百分比布局

思路:不用定宽/定高,而是将宽高都设置为百分比,这样不管屏幕大小如何变化,总是保持最初的比例不变

宽度自适应,高度无法确定

我们可以发现,元素宽度随屏幕宽度变化而变化。但这里的问题是,元素高度没办法与屏幕宽度相关联,比如这里我们想让高度为宽度的一半就无法做到,这样就无法保持原始的比例,如果是图片的话会发生明显的形变。

解决方法:去掉高度,使用padding将元素撑起来

width: 40%; /* 屏幕宽度的40% */
height 0;
padding-bottom: 20%; /* 屏幕宽度的20% */
复制代码

这样就用百分比布局做到了实现宽高都自适应的效果

用百分比做宽高自适应

代码:js.jirengu.com/peziq/3/edi…

当然,为了引入我们的主题,这里还介绍另外一种方法动态REM

动态的 rem(用 JS 动态地调整 rem)

从上面对百分比布局的分析中,我们不难发现,只需要把元素的宽高与屏幕宽度关联起来,就可以实现根据屏幕宽度来进行缩放。

换个思路,我们不使用百分比布局,而是改为固定宽高,让元素宽高两者都有的长度单位和手机屏幕宽度进行关联。

但是无论是 px、em 还是 rem 都与手机屏幕的宽度无关(vw 与屏幕宽度有关)

将 rem 与手机屏幕宽度进行关联

虽然除 vw 之外的长度单位都与屏幕宽度无关,但是1rem == html的font-size啊,这样我们只需要让font-size == 屏幕宽度(用 JS 做),即1rem == html的font-size == 屏幕宽度,这样就把长度单位 rem 与手机屏幕宽度关联起来了。

1 rem == html font-size == viewport width

我们用 JS 来实现font-size == 屏幕宽度

var pageWidth = window.innerWidth
document.write('<style>html{font-size:'+pageWidth+'px;}</style>')
复制代码

效果如下:

动态rem

每次运行 JS 都会改变 rem 的值,即 JS 动态地调整 rem,这就是动态rem

对 rem 进行微调

  1. 别忘了移动端得加一个meta viewport,加了之后才能正常显示出动态 rem 的效果

  2. 不一定非得让 rem 和屏幕宽度保持1:1

    比如,上例中我们可以让1 rem == html font-size == viewport width/10, 即1 rem == 0.1 width

    document.write('<style>html{font-size:'+pageWidth/10+'px;}</style>')
    复制代码

    这样我们在写宽高的时候就不用总是写小数了,便于我们取整数

    效果不变

    不过需要注意的是,不要把比例设置得太小,否则会出 bug。 比如你设置1 rem == 0.01width,因为在 chrome 中,默认最小字号为 12px,当屏幕宽度为 375px 时,此时 html 的 font-size 为 3.75<12,字体大小变化是不会生效的,浏览器依然按照最小的 12px 来计算。

  3. rem 可以与其他单位同时存在

    当计算出来的 rem 值特别小时就别用 rem 值了,比如上例中,如果此时 我要为元素添加 border,通过计算1px/640 == 0.0015 == 0.015 rem, 这样计算出来的 rem 值太小时,border 就会显示不精确。

    因此,当 rem 值太小时,可以不使用 rem,rem 可以与其他长度单位混用。

让 px 自动变为 rem

每次都要计算 rem 值比较麻烦,我们可以通过 SCSS 的函数@function将 px 直接翻译为正确的 rem 值。

使用步骤如下:

  1. npm config set registry https://registry.npm.taobao.org

  2. touch ~/.bashrc

  3. echo 'export SASS_BINARY_SITE="https://npm.taobao.org/mirrors/node-sass"' >> ~/.bashrc

  4. source ~/.bashrc

  5. npm i -g node-sass

  6. mkdir ~/Desktop/scss-demo

  7. cd ~/Desktop/scss-demo

  8. mkdir scss css

  9. touch scss/style.scss

    在scss文件中添加以下内容

    $ cat scss/style.scss @function px($px) {
      @return $px/$designWidth*10 + rem;
    }
    
    $designWidth: 400px; // 400px是设计稿的宽度,你要根据设计稿的宽度填写
    
    .child {
      width: px(160px);
      height: px(80px);
      margin: px(20px) px(20px);
      border: 1px solid red;
      float: left;
      font-size: 16px;
    }
    复制代码
  10. node-sass -wr scss -o css

最终的执行结果如下图:

运行结果

代码:js.jirengu.com/zokat/2/edi…

文章分类
前端
文章标签