CSS 动态REM

说明:动态REM是移动端专用的自适应方案,需要注意的是,它并不属于响应式布局,不支持在PC上使用该方案。

一、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 4 320 x 480
iPhone 5/SE 320 x 568
iPhone 6/7/8 375 x 667
iPhone 6/7/8 Plus 414 x 736
iPhone X 375 x 812

三、移动端适配方案


方案一:媒体查询

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

方案二:百分比布局

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

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

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

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

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

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

用百分比做宽高自适应

代码:http://js.jirengu.com/peziq/3/edit?html,css,output

当然,为了引入我们的主题,这里还介绍另外一种方法动态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的效果
  1. 不一定非得让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来计算。

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

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

六、让px自动变为rem


每次都要计算rem值比较麻烦,我们可以通过SCSS将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;
}
  1. node-sass -wr scss -o css
运行结果

代码:http://js.jirengu.com/zokat/2/edit?html,css,output

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。