rem适配方案

来源:互联网 发布:软件专利说明书范文 编辑:程序博客网 时间:2024/04/20 10:28

rem手机屏幕适配

rem基本知识

rem官方定义“The font size of the root element”,即以根节点的字体大小作为基准值进行长度计算。一般认为网页中的根节点是html元素,所以采用的方式也是通过设置html元素的font-size来做屏幕适配。

兼容性

目前,IE9+,Firefox、Chrome、Safari、Opera 的主流版本都支持了rem。

就算对不支持的浏览器,应对方法也很简单,就是多写一个绝对单位的声明。这些浏览器会忽略用rem设定的字体大小。

使用%单位方便使用

css中的body中先全局声明font-size=62.5%,这里的%的算法和rem一样。

因为100%=16px,1px=6.25%,所以10px=62.5%,

这是的1rem=10px,所以12px=1.2rem。px与rem的转换通过10就可以得来,

基础使用

注意,rem是只相对于根元素htm的font-size,即只需要设置根元素的font-size,其它元素使用rem单位设置成相应的百分比即可;

<style type="text/css">        html{            font-size:20px;        }        .btn{            width:6rem;            height: 3rem;            line-height: 3rem;            font-size: 1.2rem;            display: inline-block;            background-color: red;            border-radius: 5rem;            text-decoration: none;            text-align: center;        }    </style>

这里写图片描述

将上面代码html的font-size改为40px时,效果如下

这里写图片描述

上面的width,height变成了上面结果的两倍,我们只改变了html的font-size,但.btn样式的width,height的rem设置的属性不变的情况下就改变了按钮在web中的大小。

其实从上面两个案例中我们就可以计算出1px多少rem:

第一个例子:

120px = 6rem * 20px(根元素设置大值)

第二个例子:

240px = 6rem * 40px(根元素设置大值)

推算出:

10px = 1rem 在根元素(font-size = 10px的时候);

20px = 1rem 在根元素(font-size = 20px的时候);

40px = 1rem 在根元素(font-size = 40px的时候);

在上面两个例子中我们发现第一个案例按钮是等比例放大到第二个按钮,html的 font-size的改变就会导致按钮的大小发生改变,所以我们并不需要改变先前给按钮设置的宽度和高度。

使用rem实现手机屏幕适配的常用方案

以设计稿的宽度为640px,即:designWidth = 640,同时设定在640px屏宽下 1rem=100px ,即:rem2px = 100。

下面四个方案原理都是采用等比缩放的方式 —— 获得目标屏幕宽度和设计稿宽度的比,作为 rem 的基值(缩放系数),设置为html标签的字体大小。不同的只是在于性能取舍和书写习惯。

  • 方案1

    @media screen and (min-width: 320px) {html{font-size:50px;}}@media screen and (min-width: 360px) {html{font-size:56.25px;}}@media screen and (min-width: 375px) {html{font-size:58.59375px;}}@media screen and (min-width: 400px) {html{font-size:62.5px;}}@media screen and (min-width: 414px) {html{font-size:64.6875px;}}@media screen and (min-width: 440px) {html{font-size:68.75px;}}@media screen and (min-width: 480px) {html{font-size:75px;}}@media screen and (min-width: 520px) {html{font-size:81.25px;}}@media screen and (min-width: 560px) {html{font-size:87.5px;}}@media screen and (min-width: 600px) {html{font-size:93.75px;}}@media screen and (min-width: 640px) {html{font-size:100px;}}@media screen and (min-width: 680px) {html{font-size:106.25px;}}@media screen and (min-width: 720px) {html{font-size:112.5px;}}@media screen and (min-width: 760px) {html{font-size:118.75px;}}@media screen and (min-width: 800px) {html{font-size:125px;}}@media screen and (min-width: 960px) {html{font-size:150px;}}
  • 方案2

    @media screen and (min-width: 320px) {html{font-size:312.5%;}}@media screen and (min-width: 360px) {html{font-size:351.5625%;}}@media screen and (min-width: 375px) {html{font-size:366.211%;}}@media screen and (min-width: 400px) {html{font-size:390.625%;}}@media screen and (min-width: 414px) {html{font-size:404.2969%;}}@media screen and (min-width: 440px) {html{font-size:429.6875%;}}@media screen and (min-width: 480px) {html{font-size:468.75%;}}@media screen and (min-width: 520px) {html{font-size:507.8125%;}}@media screen and (min-width: 560px) {html{font-size:546.875%;}}@media screen and (min-width: 600px) {html{font-size:585.9375%;}}@media screen and (min-width: 640px) {html{font-size:625%;}}@media screen and (min-width: 680px) {html{font-size:664.0625%;}}@media screen and (min-width: 720px) {html{font-size:703.125%;}}@media screen and (min-width: 760px) {html{font-size:742.1875%;}}@media screen and (min-width: 800px) {html{font-size:781.25%;}}@media screen and (min-width: 960px) {html{font-size:937.5%;}}
  • 方案3

    var designWidth = 640, rem2px = 100;        document.documentElement.style.fontSize =           ((window.innerWidth / designWidth) * rem2px) + 'px';
  • 方案4
     var designWidth = 640, rem2px = 100;        document.documentElement.style.fontSize =           ((((window.innerWidth / designWidth) * rem2px) / 16) * 100) + '%';

详细分析可以知道,rem和px直接的转换公式可以写为:

1rem = 1 * htmlFontSizehtmlFontSize 为 html 元素的字体大小

方案3在屏宽为640px情况下的设置:

 @media screen and (min-width: 640px) {html{font-size:100px;}}

可以很明显的表现出这一点 1rem = 1 * 100px,同我们最初的设定。那么我们要得到其它屏幕大小的 htmlFontSize 值要怎么办。很简单如方案3,因为我们的采用等比缩放的方式适配,所以计算目标屏幕宽度和设计稿的宽度的比即可:

 window.innerWidth / designWidth * rem2px + 'px'

由于浏览器默认字体大小为 16px,所以当我们使用百分比作为根节点 html 的字体大小时,即html元素的font-size值设置为一个百分比值,rem 的计算方式就会改为:

  defaultFontSize = 16px  1rem = 1 * htmlFontSize * defaultFontSize

如方案2中,在屏宽为640px情况下的设置:

  @media screen and (min-width: 640px) {html{font-size:625%;}}

应用上面的公式:

  1rem = 1 * 625% * 16px

其中:625% * 16 = 6.25 * 16 = 100

所以:1rem = 1 * 100px

同样的可以得到所有屏幕大小下,html 的 font-size 值的计算公式,即为方案4:

 window.innerWidth / designWidth * rem2px / 16 * 100  + '%'

通过方案3和方案4的公式,就可以很方便的生成方案1和方案2中的css。

这里只给出了方案3和方案4对应验证页面(方案1和方案2是它们的变形): scheme3.html, scheme4.html

如下面两张图,是在屏宽为360px下的效果,通过计算目标为:1rem = 56.25px。方案3设置值为:56.25px,方案4设置值为:351.5625%

这里写图片描述

到目前为止貌似很完美的解决了问题,实际情况当然是出现了意外。在有些 Android 手机上,浏览器或 webview 的默认字体是随着系统设置的字体改变的。这样就会导致默认字体大于或小于 16px。

修改默认字体大小后,我们再看方案3和方案4。

同样在屏宽为360px下,我们调大系统字体大小,如下面的效果

设置前 html 元素的字体大小的计算值为 18px ,设置后的计算值为 65px ,由于屏幕宽度没有改变,我们的目标值,即我们在 html 元素上设置的 font-size 值也没有变化任然为 56.25px,而最终计算值出现了偏差。

这里写图片描述

分析偏差前,先来看在360px屏宽下,方案3和方案4的计算过程:

方案3:

document.documentElement.style.fontSize = 56.25pxhtmlFontSize = 56.25px1rem = 1 * htmlFontSize = 56.25px实际为:1rem = 64.6875px

方案4:

document.documentElement.style.fontSize = 351.5625%htmlFontSize = 351.5625%defaultFontSize = 18px1rem = 1 * htmlFontSize * defaultFontSize = 351.5625% * 18px = 63.28125px351.5625% * 18 = 63.28125实际为:1rem = 64.6875px

貌似方案4的计算结果很接近实际效果,而方案3偏差很大。再来比较方案3和方案4的计算公式:

// 方案3document.documentElement.style.fontSize =   window.innerWidth / designWidth * rem2px + 'px';// 方案4document.documentElement.style.fontSize =   window.innerWidth / designWidth * rem2px / 16 * 100 + '%';

方案4较于方案3其实多除了一个16,可以推测浏览器在计算 rem 的具体值时,如果 html 设置的 font-size 为 px 值时会先除以 16 ,然后再乘以 htmlFontSize。

1rem = 1 * (56.25px / 16) * 181 * (56.25 / 16) * 18 = 63.28125

方案4存在问题,是因为系统的默认字体改为了 18px ,但是我们在计算百分比是时候,还是以 16px 为基准值进行计算,所以出现偏差(计算值和实际值之间还有一点偏差这个在后面会提到)。

而在方案3中,我们其实是不考虑浏览器默认字体大小的,但在实际使用的过程中,浏览器还是除了 16 ,而此时默认字体大小为 18px。得出如下在 html 的 fontSize 设置为 px 的情况下 rem 的计算公式为:

1rem = 1 * (htmlFontSize / 16) * defaultFontSize

在系统设置的字体大小发生改变时,defaultFontSize 会跟着改变,而 16 不会变化。所以方案3虽然表面上不考虑默认字体大小的变化,只关注屏幕与设计稿之间的宽度比,但在实际计算中还是使用到了默认字体大小,而且还有一个不变的 16 在作祟,导致方案3失败。

所谓的「root element」其实不是想象的那样,一个是16,一个是18,到底取的是那个 root element 的字体大小。
ok,rem 的计算的时候,px 的方式会有一个16不随系统字体大小改变,所以我们采用百分比的方案,绕开这个问题。

采用百分比的方案4因为在计算时写死了默认字体大小 16px。所以它的偏差在于没能动态的获取默认字体大小。更新如下:

方案4.1

var designWidth = 640, rem2px = 100;var h = document.getElementsByTagName('html')[0];var htmlFontSize = parseFloat(window.getComputedStyle(h, null)                                    .getPropertyValue('font-size'));document.documentElement.style.fontSize =   window.innerWidth / designWidth * rem2px / htmlFontSize * 100 + '%';

效果如下图:

16px 的图中,设置后的 html 的 font-size 与 1rem 的实际值有偏差,同时 6.4rem 的计算值也有偏差。通过查看代码发现html的font-size使用的是: getPropertyValue('font-size') 而 1rem 使用的是 getPropertyValue('width'),偏差出在计算 font-size 的时候浏览器进行了四舍五入。rem 定义中的另一个元素「font size」也不能按字面意思使用,宣告失守。18px 中的偏差,以及上文中方案4在 18px 实际值和计算值出现的偏差都是同样的问题。所以基准值还需要修改。
  • rem、px、em的分别

    px:像素是相对于显示器屏幕分辨率而言的相对长度单位。pc端使用px倒也无所谓,可是在移动端,因为手机分辨率种类颇多,不可能一个个去适配,这时px就显得非常无力,所以就要考虑em和rem。 rem:是em的升级版,rem只会相对html的值,不会受到父级的影响,这样的好处在于:从em里的例子来讲,1rem始终会等于8px。使用的时候不需要重新计算rem此时的大小。rem因为是CSS3增加的,所以ie8或以下请无视。em:继承父级元素的大小,假设html的font-size默认为16px,body字体大小定义为50%,那么在body里字体大小就是1em=8px了。1. body选择器中声明Font-size=62.5%;2. 将你的原来的px数值除以10,然后换上em作为单位;3. 重新计算那些被放大的字体的em数值。避免字体大小的重复声明。    4. 因为em的值不固定,又会继承父级 元素的大小,你可能会在content这个div里把字体大小设为1.2em, 也就是12px。然后你又把选择器p的字体大小也设为1.2em,但如果p属于content的子级的话,p的字体大小就不是12px,而是1.2em= 1.2 * 12px=14.4px。这是因为content的字体大小被设为1.2em,这个em值继承其父级元素body的大小,也就是16px * 62.5% * 1.2=12px, 而p作为其子级,em则继承content的字体高,也就是12px。所以p的1.2em就不再是12px,而是14.4px。 

适配方案

原创粉丝点击