web app变革之rem

商业-Owen

    rem这是个低调的css单位,近一两年开始崭露头角,有许多同学对rem的评价不一,有的在尝试使用,有的在使用过程中遇到坑就弃用了。但是我对rem综合评价是用来做web app它绝对是最合适的人选之一。

rem是什么?

    rem(font size of the root element)是指相对于根元素的字体大小的单位。简单的说它就是一个相对单位。看到rem大家一定会想起em单位,em(font size of the element)是指相对于父元素的字体大小的单位。它们之间其实很相似,只不过一个计算的规则是依赖根元素一个是依赖父元素计算。

为什么web app要使用rem?

    这里我特别强调web app,web page就不能使用rem吗,其实也当然可以,不过出于兼容性的考虑在web app下使用更加能突显这个单位的价值和能力,接下来我们来看看目前一些企业的web app是怎么做屏幕适配的。

1、实现强大的屏幕适配布局:

    最近iphone6一下出了两款尺寸的手机,导致的移动端的屏幕种类更加的混乱,记得一两年前做web app有一种做法是以320宽度为标准去做适配,超过320的大小还是以320的规格去展示,这种实现方式以淘宝web app为代表作,但是近期手机淘宝首页进行了改版,采用了rem这个单位,首页以内依旧是和以前一样各种混乱,有定死宽度的页面,也有那种流式布局的页面。

    我们现在在切页面布局的使用常用的单位是px,这是一个绝对单位,web app的屏幕适配有很多中做法,例如:流式布局、限死宽度,还有就是通过响应式来做,但是这些方案都不是最佳的解决方法。

    例如流式布局的解决方案有不少弊端,它虽然可以让各种屏幕都适配,但是显示的效果极其的不好,因为只有几个尺寸的手机能够完美的显示出视觉设计师和交互最想要的效果,但是目前行业里用流式布局切web app的公司还是挺多的,看看下面我收集的一些案例:

1.亚马逊:

2.携程:

3.兰亭

    上面的网站都是采用的流式布局的技术实现的,他们在页面布局的时候都是通过百分比来定义宽度,但是高度大都是用px来固定住,所以在大屏幕的手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度还是和原来一样,实际显示非常的不协调,这就是流式布局的最致命的缺点,往往只有几个尺寸的手机下看到的效果是令人满意的,其实很多视觉设计师应该无法接受这种效果,因为他们的设计图在大屏幕手机下看到的效果相当于是被横向拉长来一样。

    流式布局并不是最理想的实现方式,通过大量的百分比布局,会经常出现许多兼容性的问题,还有就是对设计有很多的限制,因为他们在设计之初就需要考虑流式布局对元素造成的影响,只能设计横向拉伸的元素布局,设计的时候存在很多局限性。

2.固定宽度做法

    还有一种是固定页面宽度的做法,早期有些网站把页面设置成320的宽度,超出部分留白,这样做视觉,前端都挺开心,视觉在也不用被流式布局限制自己的设计灵感了,前端也不用在搞坑爹的流式布局。但是这种解决方案也是存在一些问题,例如在大屏幕手机下两边是留白的,还有一个就是大屏幕手机下看起来页面会特别小,操作的按钮也很小,手机淘宝首页起初是这么做的,但近期改版了,采用了rem。

3.响应式做法

    响应式这种方式在国内很少有大型企业的复杂性的网站在移动端用这种方法去做,主要原因是工作大,维护性难,所以一般都是中小型的门户或者博客类站点会采用响应式的方法从web page到web app直接一步到位,因为这样反而可以节约成本,不用再专门为自己的网站做一个web app的版本。

4.设置viewport进行缩放

天猫的web app的首页就是采用这种方式去做的,以320宽度为基准,进行缩放,最大缩放为320*1.3 = 416,基本缩放到416都就可以兼容iphone6 plus的屏幕了,这个方法简单粗暴,又高效。说实话我觉得他和用接下去我们要讲的rem都非常高效,不过有部分同学使用过程中反应缩放会导致有些页面元素会糊的情况。


rem能等比例适配所有屏幕

    上面讲了一大堆目前大部分公司主流的一些web app的适配解决方案,接下来讲下rem是如何工作的。

    上面说过rem是通过根元素进行适配的,网页中的根元素指的是html我们通过设置html的字体大小就可以控制rem的大小。举个例子:

html{
    font-size:20px;
}
.btn {
    width: 6rem;
    height: 3rem;
    line-height: 3rem;
    font-size: 1.2rem;
    display: inline-block;
    background: #06c;
    color: #fff;
    border-radius: .5rem;
    text-decoration: none;
    text-align: center;    
}

Demo 上面代码结果按钮大小如下图:

我把html设置成10px是为了方便我们计算,为什么6rem等于60px。如果这个时候我们的.btn的样式不变,我们再改变html的font-size的值,看看按钮发生上面变化:

html{
    font-size:40px;
}

Demo

按钮大小结果如下:

     上面的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的改变就会导致按钮的大小发生改变,我们并不需要改变先前给按钮设置的宽度和高度,其实这就是我们最想看到的,为什么这么说?接下来我们再来看一个例子:

Demo

    由上面两个的demo中我们知道改变html的font-size可以等比改变所有用了rem单位的元素,所以大家可以通过chrome浏览器的调试工具去切换第三个的demo在不同设备下的展示效果,或者通过缩放浏览器的宽度来查看效果,我们可以看到不管在任何分辨率下,页面的排版都是按照等比例进行切换,并且布局没有乱。我只是通过一段js根据浏览器当前的分辨率改变font-size的值,就简单的实现了上面的效果,页面的所有元素都不需要进行任何改变。

    到这里肯定有很多人会问我是怎么计算出不同分辨率下font-size的值?

    首先假设我上面的页面设计稿给我时候是按照640的标准尺寸给我的前提下,(当然这个尺寸肯定不一定是640,可以是320,或者480,又或是375)来看一组表格。

    上面的表格蓝色一列是Demo3中页面的尺寸,页面是以640的宽度去切的,怎么计算不同宽度下font-site的值,大家看表格上面的数值变化应该能明白。举个例子:384/640 = 0.6,384是640的0.6倍,所以384页面宽度下的font-size也等于它的0.6倍,这时384的font-size就等于12px。在不同设备的宽度计算方式以此类推。

    Demo3中我是通过JS去动态计算根元素的font-size,这样的好处是所有设备分辨率都能兼容适配,淘宝首页目前就是用的JS计算。但其实不用JS我们也可以做适配,一般我们在做web app都会先统计自己网站有哪些主流的屏幕设备,然后去针对那些设备去做media query设置也可以实现适配,例如下面这样:

html {
    font-size : 20px;
}
@media only screen and (min-width: 401px){
    html {
        font-size: 25px !important;
    }
}
@media only screen and (min-width: 428px){
    html {
        font-size: 26.75px !important;
    }
}
@media only screen and (min-width: 481px){
    html {
        font-size: 30px !important; 
    }
}
@media only screen and (min-width: 569px){
    html {
        font-size: 35px !important; 
    }
}
@media only screen and (min-width: 641px){
    html {
        font-size: 40px !important; 
    }
}

    上面的做的设置当然是不能所有设备全适配,但是用JS是可以实现全适配。具体用哪个就要根据自己的实际工作场景去定了。

    下面推荐两个国内用了rem技术的移动站,大家可以上去参考看看他们的做法,手机淘宝目前只有首页用了rem,淘宝native app的首页是内嵌的web app首页。

淘宝首页m.taobao.com

D Xm.dx.com

最后我们再来看一看他的兼容性:

Tags:

商业-Owen
商业-Owen
前端技术
上一遍
下一遍
QQ空间 腾讯微博 新浪微博 Facebook Google+

相关推荐

留下你的想法吧

  1. 云平-Owen 云平-Owen says:

    @blinkcat,rem是可以合并雪碧图的,viewport设置确实简洁,但是过于粗暴,全局都进行缩放,有时候我布局并不希望全局缩放,部分布局希望不用缩放,所以使用rem,不过具体使用什么方法大家都可以根据实际情况衡量。并不是每个人都喜欢使用sass,所以在px转rem这块我做了一个在线转换工具:http://520ued.com/tools/rem

  2. 顾陌博客 says:

    学习了。最近看淘宝天猫的页面设计,有好多没懂的…o(╯□╰)o

  3. seanlo says:

    请问,在底部用js改变html的font-size的话,会造成整个页面重新布局吗?实际使用中有没遇到页面元素因为尺寸改变了而闪烁的情况?

  4. 陈星 says:

    我想问下 如果用REM的话 设计稿为750的怎么换算呢

  5. 叶小钗 says:

    亲,文章不错啊,但是好多错别字哦

  6. cshuawei says:

    用js控制根元素的大小来适配有个不好的地方,页面类容大的时候,加载时页面会有明显的动态变化,用响应式样式控制最好

  7. 小狼 says:

    小白请教:
    我有一张设计图1080 * 1920,想用rem做自适应。
    疑问如下:
    1.明明是移动端的设计,,,为啥这么大?
    2.怎么根据设计图选html的font-size大小?

  8. 张欣欣 says:

    真的很棒,过两天要开始做移动端,特地过来学习。谢谢

  9. cococe says:

    小狼:你可以把设计图改变大小至宽度为640px,再进行切页面。

  10. 林龙博客 says:

    rem用起来挺实用的

  11. summer says:

    js怎么实现全兼容呢?设计师给的不管什么分辨率的图,我该怎么转换成rem呢?

  12. 查了下使用px,em,rem等单位的优势和弱点,真感觉得转变写法用rem了

  13. 晓楷周 says:

    rem固然好用,但是QQX5内核浏览器不支持rem单位,在大部分android 机上的微信页面不起作用

  14. 叁弦 says:

    (function (doc, win) {
    var docEl = doc.documentElement,
    resizeEvt = ‘orientationchange’ in window ? ‘orientationchange’ : ‘resize’,
    recalc = function () {
    var clientWidth = docEl.clientWidth;
    if (!clientWidth) return;
    docEl.style.fontSize = 20 * (clientWidth / 320) + ‘px’;
    };

    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener(‘DOMContentLoaded’, recalc, false);
    })(document, window);

    这才是重点

  15. Rango says:

    三星GT-N7100 安卓4.3 微信最新版内置浏览器表示不支持 rem,唉

  16. miacle says:

    超赞,特别详细。

  17. angela says:

    受教了,之前做的web app的文字都是px写的,尺寸都是百分比写的,看过这个之后,我决定趁着这次做页面优化,把现在的工程用rem优化一遍

  18. 少年 says:

    使用viewport方式遇到一个坑,当点击输入框的时候页面会缩放,这个是否不可避免??

  19. miss usa says:

    你说的兼容所有的JS具体是怎样的。想一睹代码真容

  20. 周杰伦 says:

    我用你的方法做移动前端框架,但是在一些手机上的浏览器正常,但是在webapp 上看就显示不正常了,就好像是计算的rem值失效了,这个怎么办

  21. houfumao says:

    seanlo
    2015.10.15 at 21:03
    请问,在底部用js改变html的font-size的话,会造成整个页面重新布局吗?实际使用中有没遇到页面元素因为尺寸改变了而闪烁的情况?

    回答:会造成闪烁,但是可以现在css里根据屏幕 初始化一遍html 的font-size,然后在用js计算的话,区别不是很大。
    例如:
    @media only screen and (max-width: 320px){html{font-size: 9px;} }
    @media only screen and (min-width: 320px) and (max-width: 352px){html{font-size: 10px;} }
    @media only screen and (min-width: 352px) and (max-width: 384px){html{font-size: 11px;} }
    @media only screen and (min-width: 384px) and (max-width: 416px){html{font-size: 12px;} }
    @media only screen and (min-width: 416px) and (max-width: 448px){html{font-size: 13px;} }
    @media only screen and (min-width: 448px) and (max-width: 480px){html{font-size: 14px;} }
    @media only screen and (min-width: 480px) and (max-width: 512px){html{font-size: 15px;} }
    @media only screen and (min-width: 512px) and (max-width: 544px){html{font-size: 16px;} }
    @media only screen and (min-width: 544px) and (max-width: 576px){html{font-size: 17px;} }
    @media only screen and (min-width: 576px) and (max-width: 608px){html{font-size: 18px;} }
    @media only screen and (min-width: 608px) and (max-width: 640px){html{font-size: 19px;} }
    @media only screen and (min-width: 640px){html{font-size: 20px;} }

  22. houfumao says:

    陈星
    2015.10.16 at 11:54
    我想问下 如果用REM的话 设计稿为750的怎么换算呢

    回答:可以直接把图片转换为640的 ,或者js计算html的font-size呀

  23. houfumao says:

    summer
    2015.11.06 at 17:32
    js怎么实现全兼容呢?设计师给的不管什么分辨率的图,我该怎么转换成rem呢?

    回答:要看设计师给的手机尺寸 等比例来计算就好了。

  24. houfumao says:

    晓楷周
    2015.11.10 at 11:18
    rem固然好用,但是QQX5内核浏览器不支持rem单位,在大部分android 机上的微信页面不起作用

    回复:目前我没发现这种情况呢..。。。?

  25. houfumao says:

    cshuawei
    2015.10.20 at 10:38
    用js控制根元素的大小来适配有个不好的地方,页面类容大的时候,加载时页面会有明显的动态变化,用响应式样式控制最好

    先用响应式,再用js

  26. houfumao says:

    小狼
    2015.10.23 at 15:03
    小白请教:
    我有一张设计图1080 * 1920,想用rem做自适应。
    疑问如下:
    1.明明是移动端的设计,,,为啥这么大?
    2.怎么根据设计图选html的font-size大小?

    回复:为何移动端会有1080*1920的图。。。

  27. houfumao says:

    少年
    2015.11.19 at 18:02
    使用viewport方式遇到一个坑,当点击输入框的时候页面会缩放,这个是否不可避免??

    回复: 禁止缩放/放大

  28. 鱼蛋 says:

    这个如果要用再微信浏览器上药如何适应呢?楼上有人说不能兼容

  29. 优图艾灸 says:

    蛮不错的,是一个趋势

  30. 盒盒盒 says:

    豁然开朗 但是有个地方不知道对不对 我理解的px应该是相对单位吧。。

  31. surmerming says:

    640px的基准20px应该是可以自己随便定义的吧

  32. rem学习者 says:

    楼主,我用rem写了一个页面,可是放在手机上,QQ浏览器和微信浏览器并不兼容,请问我该加些什么兼容呢?楼主,能给我发一个完整的做过兼容的页面吗?不需要写什么内容,只要把html页面做完兼容的框架就行,麻烦了楼主,这几天一直研究这个,还是没弄明白,求楼主救命啊

  33. rem学习者 says:

    楼主,如果可以,请发到我邮箱吧,十二分感谢!

  34. 老王 says:

    (function(doc, win) {
    var docEl = doc.documentElement,
    isIOS = navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
    dpr = isIOS ? Math.min(win.devicePixelRatio, 3) : 1,
    dpr = window.top === window.self ? dpr : 1, //被iframe引用时,禁止缩放
    resizeEvt = ‘orientationchange’ in window ? ‘orientationchange’ : ‘resize’;
    docEl.dataset.dpr = dpr;
    var recalc = function() {
    var width = docEl.clientWidth;
    if (width / dpr > 1080) {
    width = 1080 * dpr;
    }
    docEl.dataset.width = width
    docEl.dataset.percent = 100 * (width / 1080);
    docEl.style.fontSize = 100 * (width / 1080) + ‘px’;
    };
    recalc()
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    })(document, window);

    以上,注意出现1080 的地方,这里改成设计图的宽度即可,这段代码的好处是根元素font-size是100 计算方便,若要给页面设置宽度 1080 = 10.8rem 640 = 6.4rem 等,字号的话直接根据设计图除以100即可,注意头部 别忘了。

    不妥之处,请指正。

  35. 颜海镜 says:

    很赞啊,决定在百度经验的页面试用下

  36. vikki呀 says:

    文中给出的淘宝触屏和dx有一点不同,前者的字体是固定的px,而后者的字体也用了rem,因此在平板和普通手机状态下,前者字体固定,后者字体大小会随之变。不知提倡哪种更好?

  37. yinz says:

    font-size 最小只能设置12px