有一道高频的面试题经常会出现,请你讲一下em和rem的区别。
1. em与rem的区别
这个题目其实很简单,基本上都能说出来,他们的本质区别就是参照的对象不同。
- em是相对父元素的字体大小,如果父元素的字体大小是14px,那么它子元素的2em就是28px,不同父元素的子元素的2em的实际大小是可能不同的。
- rem是相对于根元素,即html元素,如果html的字体大小是14px,那么在任何地方的2rem都是28px。
2. 为什么要用rem?
可能大多数人就回答道这里就完了,那么有没有思考过为什么会有rem的存在,难道仅仅只是为了是全文都有一个统一的相对元素吗。
当然不可能这么简单,rem的出现及使用多用于移动端开发中,我们知道,移动端的设备宽度是不定的,如果我们使用固定的大小,那么在不同大小的设备上就会出现布局错乱、留白、残缺等现象的出现。
举个例子,假设我们拿到的设计图宽度为750px,实际的设备宽度也是750px,这种情况真是好,实际与设计图大小一样,我们只需要把每个元素的大小全部按照设计图的大小开发就可以了。但是如果实际设备宽度只有375px呢,缩小了一般,这是如果我们还是按照原来的大小进行开发,在设备上必然是无法完全显示的。这是我们就需要将开发的元素实际大小都要缩小为设计图的一半,但是缩小后的只能在375px的设备上正常显示,如果换做其他设备,布局又会改变。
3. 如何解决
这时就可以用rem来解决,我们假设在设计图中1rem = 100px,假设有个元素在设计图中的大小为50px,我们就可以写成 0.5rem,如果是80px,可以写成0.8rem。现在我们把开发后的内容放到实际设备中,设备宽度正好为750的话,那么1rem还是等于100px,如果设备为375px,我们只需要把1rem设置为50px,即根元素的字体大小为50px;如果设备大小为400px,那么1rem就应该为 (400/750)*100 = 53.3px。
4.动态计算
因为设备的大小我们是无法预知的,所以1rem的大小在不同设备上也就不同,如果我们在加载时知道了设备的宽度,我们就可以根据这个宽度来动态的计算出在该设备上1rem究竟应该是多少,然后设置到html元素上。假设设计图宽度为designWidth,实际设备宽度为windowWidth,那么可以计算出实际的1rem = (designWidth/windowWidth)*100。这里的100为我们在设计图中设置的1rem的大小,也叫基准值。
5. 为什么选100px作为基准值
上面讲到我们设置的基准值为100px,当然也是可以设置50、14等来作为基准值,那我们为什么要选100作为基准值呢?
主要还是 为了方便计算,20px换算后为0.2rem,16px换算后为0.16rem。如果基准值为14的话,20px = 20/14 = 1.43rem,很明显在计算上要麻烦很多。既然这样,有人问了,我如果选1px作为基准值岂不是更方便,14px就为14rem,20px就为20px。有个问题不要忽略了,浏览器的最小字体大小为12px,所以设根元素的字体大小为1px是不可以的,只能大于12px,大于12的就100计算最为方便。
我的网站:http://www.dzyong.top/ ,觉得还不错的话就关注我吧,不错过我的每一篇推送,微信搜索:【前端筱园】
6. 实际案例
来看一个我们都熟悉的应用《淘宝》,淘宝的首页就是一个嵌入网页,网址:https://main.m.taobao.com/。它就是使用的rem,打开控制台找到根元素html,当我改变页面宽度时,可以看到html元素的宽度也在改变。
当我尝试改变窗口使根元素font-size大小为100px时,看到此时窗口的大小为375px,375px也真是设计师常用的一个尺寸,此时的font-size为100,说明淘宝的基准值就是我们说的100,还可以知道当时设计图的宽度为375px。
7. 代码实现动态改变根元素大小
计算代码如下,当页面大小改变后需要重新计算:
$(function(){
function setRem(){
var windowWidth = $(window).width();
console.log(windowWidth);
var rem = parseInt(windowWidth/750*100)+'px';
$('html').css('font-size',rem);
console.log(rem)
}
setRem();
var timer;
$(window).on('resize',function(){
timer=setTimeout(function(){
clearTimeout(timer);
setRem();
},50)
})
})