这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
em 和 rem
em 和 rem 都是众多长度单位的中的一种,MDN 给出的定义分别是
em是一个相对长度单位,这个单位表示元素的
font-size的计算值。如果用在font-size属性本身,它会继承父元素的font-size。
rem代表根元素的
font-size大小(例如<html>元素的font-size)。当用在根元素的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% */
这样就用百分比布局做到了实现宽高都自适应的效果
代码: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>')
效果如下:
每次运行 JS 都会改变 rem 的值,即 JS 动态地调整 rem,这就是动态rem。
对 rem 进行微调
-
别忘了移动端得加一个
meta viewport,加了之后才能正常显示出动态 rem 的效果 -
不一定非得让 rem 和屏幕宽度保持1:1
比如,上例中我们可以让
1 rem == html font-size == viewport width/10, 即1 rem == 0.1 widthdocument.write('<style>html{font-size:'+pageWidth/10+'px;}</style>')这样我们在写宽高的时候就不用总是写小数了,便于我们取整数
不过需要注意的是,不要把比例设置得太小,否则会出 bug。 比如你设置
1 rem == 0.01width,因为在 chrome 中,默认最小字号为 12px,当屏幕宽度为 375px 时,此时 html 的 font-size 为 3.75<12,字体大小变化是不会生效的,浏览器依然按照最小的 12px 来计算。 -
rem 可以与其他单位同时存在
当计算出来的 rem 值特别小时就别用 rem 值了,比如上例中,如果此时 我要为元素添加 border,通过计算
1px/640 == 0.0015 == 0.015 rem, 这样计算出来的 rem 值太小时,border 就会显示不精确。因此,当 rem 值太小时,可以不使用 rem,rem 可以与其他长度单位混用。
让 px 自动变为 rem
每次都要计算 rem 值比较麻烦,我们可以通过 SCSS 的函数@function将 px 直接翻译为正确的 rem 值。
使用步骤如下:
-
npm config set registry https://registry.npm.taobao.org -
touch ~/.bashrc -
echo 'export SASS_BINARY_SITE="https://npm.taobao.org/mirrors/node-sass"' >> ~/.bashrc -
source ~/.bashrc -
npm i -g node-sass -
mkdir ~/Desktop/scss-demo -
cd ~/Desktop/scss-demo -
mkdir scss css -
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; } -
node-sass -wr scss -o css
最终的执行结果如下图: