CSS零碎之em、rem

移动端的开发基本不多直接使用px做为单位了,目前最经常使用的是rem。不过在这以前其实还有个em单位,和rem长得很是的像,那么它们有什么区别呢?又有什么不同的适用场景呢?javascript

注意:不管使用em,仍是rem,客户端最终解析的值依旧是px!

em:相对父级元素字体大小的倍数

从title的解释就能够看出,em的基准是其父级元素,不过这个父级元素要求是设置有font-size值的,以下面的例子:css

<div class="father" style="font-size:20px;">
    <div class="son"  style="font-size:2em;"></div>
</div>

那么son的字体大小就是2 * 20px = 40px,此时,若是father的字体大小变化了,那么son的也会跟着变化。假如没有父元素,则基准就是body(因为默认浏览器默认字体为16px,因此默认状况1em=16px)。html

rem:相对 html 根元素字体大小的倍数

跟上面解释body基准时的差很少,默认状况下1rem=16px。此时,只要根元素字体大小不变,那么相对于它的rem就不会变。
对于移动端的各类机型来说,因为不一样的机型屏幕尺寸、分辨率都不同,不太可能使用相同的根元素字体大小做为基准,因此所谓rem布局,就是经过js动态计算出不一样机型的根元素字体大小值,来对页面进行等比例的缩放,达到适配大部分机型的效果。
那么具体如何去设定这个基准呢?
假设把手机屏幕宽度均分红10等份(由于rem布局就是针对宽度去作设定的),规定其中的一份做为根元素的font-size值,那么根元素font-size值就可由下述公式得到:前端

document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

在这个基准下,那么1rem的值也随之获得了:java

1rem = document.documentElementstyle..fontSize = document.documentElement.clientWidth / 10 + 'px';

那么,不一样屏幕的机型因为屏幕宽度不一样,也就获得了在"屏幕宽度均分红10等份"这个标准下的rem相对值。比较完整的计算方式以下:git

// set 1rem = viewWidth / 10
function setRemUnit () {
  var rem = docEl.clientWidth / 10
  docEl.style.fontSize = rem + 'px'
}

setRemUnit()

// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
  if (e.persisted) {
    setRemUnit()
  }
})
注意:这里的标准 "10"能够是任一值,只要跟下面转换公式中用到的标准值保持一致便可,这里只是为了计算方便才这么设定。

这样,rem的基础生态就搭建好了。那么如何基于这套标准应用到开发中去呢?github

在继续以前,先来了解下"像素"这个知识点,由于接下来都会用到它的概念。
像素分为两种:设备像素和CSS像素
一、设备像素(device independent pixels): 设备屏幕的物理像素,任何设备的物理像素的数量都是固定的
二、CSS像素(CSS pixels): 又称为逻辑像素,是为web开发者创造的,在CSS和javascript中使用的一个抽象的层
在pc端,css像素和物理像素是1:1的关系;而在移动端,因为相似retina的各类高清屏的出现,css像素和物理像素的关系通常是1:2或者1:3,即1个css像素容纳2到3个物理像素,实现高清的效果。

通常移动端页面的开发流程是:设计人员以某个机型做为标准,设计好UI。前端开发针对这个机型的UI作开发,而后其它机型相对的去等比例缩放。
这里以iphone6做为标准(由于实际开发中基本也是用它作设计),它的物理像素为750x1334,css像素为375*667,假设UI上图片a的宽度为140,那么如何把它转换成以rem为单位的值呢?
如今屏幕宽度是已知的10rem,要求UI上宽140的rem值,假设为X,由下图能够很容易的获得比例关系:web

屏幕宽度/UI宽度 = x/140 = 10rem / 750
=》
x = 140 / 750 * 10 rem

image
通常能够在sass中经过封装预处理函数进行这个转换过程:编程

$UI_WIDTH: 750;

@function px2rem($px) {
  @return ${ $px / $UI_WIDTH * 10 }rem;
//=>or @return ${ $px / 75 }rem;
}

img{
  width: px2rem(140);
}

这就是"rem布局"原理的整个实现过程!浏览器

而随着社区各类工具的完善,如今也无需手动去使用如px2rem的这种预处理函数去转换,比较流行的作法是使用postcss的postcss-px2rem插件去自动处理,开发时仍然按照px的方式去编程,postcss配置例:

postcss: function() {
  return [px2rem({remUnit: 75})]; //设置基准值,75是以iphone6的标准
}

这里的remUnit设置是有必定规则的,好比屏幕宽度等分红10份,当UI以iphone6(即物理像素宽度750)设计时,remUnit=75;当UI以iphone5(即物理像素宽度640)设计时,remUnit=64。能够看出它中遵循以下公式:

remUnit = 物理像素宽度 / 设定的屏幕宽度等分值;

至于具体的js等分逻辑封装能够参看手淘的flexible

em 仍是 rem ?

那么在实际开发中,究竟适用em仍是rem呢?记住以下原则便可:

  1. 若是属性值根据元素的font-size得到,则使用em,如padding、margin、line-height等
  2. 其余状况都使用rem
本文收录在我的的Github上 https://github.com/kekobin/bl... ,以为有帮助的,欢迎start哈。支持原创,未经本人赞成,请勿转载!
相关文章
相关标签/搜索