美文网首页h5技术专题前端开发
手机端页面自适应解决方案—rem布局

手机端页面自适应解决方案—rem布局

作者: 梁相辉 | 来源:发表于2015-11-30 17:11 被阅读108490次

    该方案目前已过时,这里是更加完美的替代方案——rem布局(进阶版)


    相信很多刚开始写移动端页面的同学都要面对页面自适应的问题,当然解决方案很多,比如:百分比布局,弹性布局flex(什么是flex),也都能获得不错的效果,这里主要介绍的是本人在实践中用的最顺手最简单的布局方案——rem(什么是rem)布局

    rem布局非常简单,首页你只需在页面引入这段原生js代码就可以了

        (function (doc, win) {
            var docEl = doc.documentElement,
                resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
                recalc = function () {
                    var clientWidth = docEl.clientWidth;
                    if (!clientWidth) return;
                    if(clientWidth>=640){
                        docEl.style.fontSize = '100px';
                    }else{
                        docEl.style.fontSize = 100 * (clientWidth / 640) + 'px';
                    }
                };
    
            if (!doc.addEventListener) return;
            win.addEventListener(resizeEvt, recalc, false);
            doc.addEventListener('DOMContentLoaded', recalc, false);
        })(document, window);
    

    如何使用?

    这是rem布局的核心代码,这段代码的大意是:
    **如果页面的宽度超过了640px,那么页面中html的font-size恒为100px,否则,页面中html的font-size的大小为: 100 * (当前页面宽度 / 640) **
    于是,问题来了,为什么要这样?别急,我先来一一回答

    1. 为什么是640px?
      对于手机屏幕来说,640px的页面宽度是一个安全的最大宽度,保证了移动端页面两边不会留白。注意这里的px是css逻辑像素,与设备的物理像素是有区别的。如iPhone 5使用的是Retina视网膜屏幕,使用2px x 2px的 device pixel 代表 1px x 1px 的 css pixel,所以设备像素数为640 x 1136px,而它的CSS逻辑像素数为320 x 568px。
      如果要切移动端页面,你可以先把效果图宽度等比例缩放到640px,很好用。
    2. 为什么要设置html的font-size?
      rem就是根元素(即:html)的字体大小。html中的所有标签样式凡是涉及到尺寸的(如: height,width,padding,margin,font-size。甚至,left,top等)你都可以放心大胆的用rem作单位。
      如果你把html的font-size设为20px,前面说过,rem就是html的字体大小,那么1rem = 20px。
      此时,此时宽60px,高40px的元素样式就这样设置如下 ↓
    width: 3rem;
    height: 2rem;
    

    那要是宽55px,高37px呢?然后经过换算,,设置如下 ↓

    width: 2.75rem;
    height: 1.85rem;
    

    是不是发现这换算起来有点麻烦啊,,,(当然,你要是心算帝请无视)
    如果我们一开始把html的font-size设为100px呢?此时1rem = 100px,那么上面的宽55px,高37px的元素样式就可以这么设置 ↓

    width: 0.55rem;
    height: 0.37rem;
    

    是不是换算起来简单多了?!
    (当然可能有同学问,为什么不一开始把html的font-size设为1px呢,这样换算起来也简单,答:浏览器一般都有最小字体限制,比如谷歌浏览器,最小中文字体就是12px,所以实际上没有办法让1rem=1px。)
    根据上面的js代码,如果页面宽度低于640px,那么页面中html的font-size也会按照(当前页面宽度/640)的比例变化。这样,页面中凡是应用了rem的作尺寸单位的元素都会随着页面变化而等比例缩放了!

    1. 都哪些情况可以用rem布局?
      大部分情况下都可以用rem布局这个方法,当然具体还要看情况而定。拿我们公司项目举例,只有底部的导航不用rem,而是用的flex布局。因为导航点击最多,所以给它一个固定的大小(其实就是高度固定,宽度自适应的方案)。大家可以看看淘宝的这个手机页面 淘宝手机站,基本就是这种感觉,底部导航和顶部搜索框用的高固定,宽自适应的方案,其余的部分基本都是随着浏览器宽度变化在等比例缩放。

    最终页面代码首页代码大致如下

    <!DOCTYPE html>
    <html lang="en">
    <head> 
     <meta charset="UTF-8">  
     <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">  
    <script>   
    (function (doc, win) {
            var docEl = doc.documentElement,
                resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
                recalc = function () {
                    var clientWidth = docEl.clientWidth;
                    if (!clientWidth) return;
                    if(clientWidth>=640){
                        docEl.style.fontSize = '100px';
                    }else{
                        docEl.style.fontSize = 100 * (clientWidth / 640) + 'px';
                    }
                };
    
            if (!doc.addEventListener) return;
            win.addEventListener(resizeEvt, recalc, false);
            doc.addEventListener('DOMContentLoaded', recalc, false);
        })(document, window);
    </script> 
     /*你引进的资源*/
    <title>标题</title> 
    </head>
    <body>
     /*你的代码*/
    </body>
    </html>
    

    rem布局实践应用

    Iphone 6 下页面效果 Iphone 4 下页面效果

    相关文章

      网友评论

      • cd4b1b7a192b:大神,求指教,我写了一个静态页面,手机端看有些问题,能否指教
        梁相辉:@清扬婉兮_7737 如果你能把遇到的问题描述清楚就好了:joy:
      • Wendell_d925:!new function(){var a=this;a.width=750,a.fontSize=100,a.widthProportion=function(){var b=(document.body&&document.body.clientWidth||document.getElementsByTagName("html")[0].offsetWidth)/a.width;return b>1?1:b},a.changePage=function(){document.getElementsByTagName("html")[0].setAttribute("style","font-size:"+a.widthProportion()*a.fontSize+"px !important")},a.changePage(),window.addEventListener("resize",function(){a.changePage()},!1)};

        示例代码:

        <!DOCTYPE html>

        <html>

        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

        <meta name="apple-mobile-web-app-capable" content="yes">

        <meta name="apple-mobile-web-app-status-bar-style" content="black">

        <head>

        /*每个页面都需要引入rem.js 代码如上*/

        <script src="js/rem.js"></script>

        <style>

        /*设计图中div的宽度为750px 高度为100px*/

        div{width: 7.5rem;height: 1rem;}

        </style>

        </head>

        <body>

        <div>内容</div>

        </body>

        </html>
        吻妳乄承諾今世_4c42:你这个是以苹果6的尺寸设计的吗,我在苹果6上的根大小是50px咋回事
      • 明月888:最终页面代码首页代码大致如下 的示例 实测html 的font-size: 58.5938px; 不是100px 这是为啥 但是把示例里的meta缩放标签删掉就是100px了 这是为啥?
      • 802486935199:为啥设50px为基准呢,
      • 饼yuea:和flexible 好像没有区别的
      • 饼yuea:你好,这和淘宝的flexible 有神魔区别呢?
      • HiZ小明:谢谢楼主的分享,真的很好用。
      • 我叫小阿伟:楼主你好问个问题 1.我的效果是750的 我需要吧效果图缩小到640 然后按照640的尺寸去测量来换算rem,2图片用750的吗?图片也得设置rem的宽度吧
      • b44cb4dcd563:楼主 这种方法字在手机上合适但是电脑上看着很大怎么办 望解答:persevere:
      • 44c05db69092:使用这段代码。刷新会先变小,然后在正常。是怎么回事?
      • 诠释丶那一世的唯美:有网站案例么 楼主
      • haojie2021:还是感觉媒体查询写出的代码有很强的艺术性和逻辑性。
      • 2e4d1dfd1767:要写手机端了。注册加关注。。。现在就是不知道怎么调整大小
      • 0cbd9bccdeec:请问,大于640的时候,为什么根元素字体大小还是100px?
      • c89a4f04cd33:加了这段JS.还需要写@media(font-size:10px),比如这种吗
        c89a4f04cd33:你好,我想问下IE的HTML5和css3兼容性怎么解决?网上查的资料。下载以后也没用
        c89a4f04cd33:@_minooo_ @_minooo_ 好的。意思就是按640px最大的宽。用rem做出来。直接适应各个屏幕的手机。楼主厉害
        梁相辉:@浪费大哥 不需要了
      • ced02376c513:楼主,我很认真看了你的文章,有个问题虚心的想请教,为什么当设备的宽度大于等于640px的时候要固定html的字体大小为100px,这样的话如果我是iPad设备宽度为768px. 设备宽度设置成6.4rem就不是一屏的了
        梁相辉:@FighGirl雯雯 按照分辨率是72像素/每英寸,换算出来的。
        6fc8d1661680:@_minooo_ 这个22.5cm是怎么算出来的啊
        梁相辉:@一世繁华疑是梦 这里640px 特指css像素,换算成厘米大概是22.5cm,你确定你的ipad宽度超过了22.5cm???
      • 王文_5a51:楼主,您好 :
        能把您例子中的代码 发给我一份吗 (刚入行几天的新手)1985880936@qq.com。谢谢了。我想参考下,您这样说,我有点糊。
      • 692a96708302:楼主,我用的你的这个rem的布局,但是在UC浏览器上打开,p标签里面的字会被无缘无故的缩小。这是为什么呢
        梁相辉:@你听得到_15ed 文章里的demo在你说的浏览器里效果如何?
        692a96708302:@_minooo_ 我的这个字体不是被放大了,而是被无缘无故的缩小了。感觉写的font-size的rem就像没有效果一样
        梁相辉:@你听得到_15ed http://www.jianshu.com/p/985d26b40199 文章底部常见问答第五条你看下,同时建议使用rem进阶版布局。
      • 张张张啊先生:注册只为给你评论点个赞,写的太好了
      • 儒丶:不是很能理解这段代码,怎么就是100px设置了font-size。不是大于650px么?
      • e81c0a5e2810:手机ren布局应用,可以发一份给我吗?邮箱:162037@qq.com
      • ndibao:楼主 你最下面两个图 是什么软件啊?
        布局实践应用的
        梁相辉: @ndibao 公司的移动端web项目,如果你有兴趣,可以微信搜索 嘟嘟微生活
      • f90395e1d0f8:加载js后,任何情况下,都相当于html为100px吗,想要得到44px 的高度,直接写成0.44rem就成了吗?我试过不太行,得到的不是44px
      • 原点_bf91:希望大神以后多发发这样的文章,像我这样的菜鸟受益匪浅,谢谢!
      • 801a76d71c45:是不是还需要设置什么东西 直接用不了吧 需要设置什么css吗
        梁相辉:只需在页面head引入这段js就可以了,不需要额外设置什么。
      • b305cbf608f9: docEl.style.fontSize = 100 * (clientWidth / 640) + 'px'如果我们一开始把html的font-size设为100px,那么当屏幕是320宽这时的字体就是默认50px;此时div的宽就得除2了
      • JackZhOOOOZ:博主你好,你的截图里用的啥子工具啊???win 系统的 chrome咋个没有这个工具啊?
        d652ef8bf6fd:他是问截图里那个调试工具是什么?没问你用什么截图
        梁相辉:@JackZhoOou 叫FastStone Capture,百度下就知道了,一个小巧的截图工具。
      • c25d3c144030:还在摸索中!
      • c25d3c144030:很好用啊 !
      • 19d5b902f5ce:为什么垂直居中或者行高在安卓上面会向上偏移几像素?不管是使用padding
        或者line-height在或者css3的flex布局始终都不会居中。越小高度越明显。高度大了反而不明显。请问这是什么问题?
        最新的REM布局我也看了。但这一套比较符合我公司的要求
      • coderLfy:这样写有缺陷?开始加载的时候会造成一个闪一下,然后进行适配,因为这是用js来控制html的字体,只能用个loding来做个加载的等待,想问,这个布局既然是你觉得最好的布局,你在解决这种问题有没有更好的方案?
        c25d3c144030:@_minooo_ loading的方式 怎么写
        c25d3c144030:@_minooo_ 怎么写啊
        梁相辉:@coderLfy 哈哈,我现在用的就是loading的方式。
      • 79fa269fdbf9:看了楼主的文章之后,彻底理解了rem布局。
        另外想请教下:flex布局实现等比例缩放应该更简单吧,为什么不用flex布局呢
        梁相辉:@一歩 可以和rem布局一起使用的。你可以试试。另外本人推荐使用 rem布局的进阶版 http://www.jianshu.com/p/985d26b40199
      • d7fdb65d99de:楼主,我刚刚试了你的进阶版方案,觉得有点问题,假如设计图是750的,我写一个占一半的宽度的div,也就是375,那我肯定写width:3.75rem,但是如果设计图如果是680的,我就得写width:3.4rem,那这样宽度不是不定了吗?怎么还能保证这个块占屏幕的一半?还有,假如设计图是750的,我写了一个0.75rem宽度的块,在iphone5上会出现滚动条,在pad上又会出现留白,请问这个怎么解决?所以我觉得还是老方案比较好用,不论什么设备永远都是等比例的。
        梁相辉:@d7fdb65d99de
        你说的问题,在新方案中需要简单的判断下就行了
        1,像你说的,如果该元素尺寸很大,那就将其宽度设为百分比就行了,最极端的例子就是
        等屏宽的图片了,这点和老版的效果一样,此时元素将随着屏幕大小而等比缩放
        2,如果该元素很小呢,比如w:120px h:80px 那就愉快的写rem了,这种情况下,无论什么设备,显示的尺寸也是固定的,一方面很好的还原了效果图,另一方面也顺应了当前大多数移动端页面,屏幕越大,看的越多的潮流,而不是简单的粗暴的等比缩放就行了。

      • 阿狸力呓:请问js里面的数值怎么办
        梁相辉:@阿狸力呓 推荐你使用rem布局最新方案
        http://www.jianshu.com/p/985d26b40199
      • 66429d77cd59: (function (doc, win) {
        var docEl = doc.documentElement,

        你的代码上面这两个参数什么意思 求教
        梁相辉:@66429d77cd59 意思都在代码里呀,那俩参数只是形参,你要看后面引用时候括号里跟的实参
      • 69a7b6c3b4c7:另外请问一下楼主 使用淘宝的flexible.js就不用写meta的标签去设置viewport了是吗
        梁相辉:@PARADISELIN 嗯,代码自动帮你设置viewport http://www.jianshu.com/p/985d26b40199
      • 69a7b6c3b4c7:您好 请问移动端fixed固定底部不会出现问题吗
      • 洛_小七:用了楼主的代码,效果不错,在手机上显示的都很好,就是在ipad上图标、间距过大,想问这个怎么解决
        洛_小七: @_minooo_ 谢谢楼主,对我的帮助很大
        梁相辉:@努力撑起一片天空 你好,rem布局有重大更新,能更完美解决移动端自适应问题,请访问最近更新的 rem布局(进阶版)
        http://www.jianshu.com/p/985d26b40199 希望能帮到你。
      • 程序媛喵喵:楼主,我写的是全局html的 font-size:62.5%,然后字体就是设计稿的一半大小。比如设计稿字体为28px。我的就是1.4rem。就是相当于14px*2 为28px。这样对吗 ,我没有引入你的这段js,也没有给页面定宽度,只是用了个这个<meta id="viewport" name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1">。。。。想问下,我这样对吗?谢谢回复~ :blush:
        梁相辉:@赵大猫不喵喵 你好,rem布局有重大更新,能更完美解决移动端自适应问题,请访问最近更新的 rem布局(进阶版)
        http://www.jianshu.com/p/985d26b40199 希望能帮到你。
        程序媛喵喵:有效果啊,我就是这样做的,所以问问他可不可以的,有什么弊端
        洛_小七:@赵大猫不喵喵 之前别人也告诉我这样做,但是没有效果,这个你解决了吗
      • Mr周小瑜:学习了,word哥!
      • 53b8f1484194:你好,如果设计师出图是720px,我们做750px怎么自适应
        梁相辉:@53b8f1484194
        1。直接就按照效果图上的尺寸写样式;
        2。如果页面效果与设想的有出入,只需要将效果图,等比缩放至宽度640px,然后按照缩放后的效果图上的尺寸给样式。
      • 大桔子123:看了楼主的文章的,觉得很实用,正想用在项目中,,可看了淘宝的flexible.js,,,他好像还结合了dpr,来动态改变html的font-size大小,,,楼主这个方案没有考虑到dpr的问题,,,会不会造成一些情况下,显示模糊的问题
        梁相辉:@大橘子小锦 清晰问题是能够保证的,我这个方案的特点就是等比例缩放,也就是说,屏幕大,页面元素就大;对于你说的淘宝的方案,它那个是屏幕大,显示的更多,另外淘宝的很好的解决了移动端1px的问题。我在项目[react-study](https://github.com/minooo/React-Study)中用的就是他们的这个高清方案。
      • 吃葡萄只吃葡萄皮:兼容ipad吗?
        梁相辉:@吃葡萄只吃葡萄皮 你好,rem布局有重大更新,能更完美解决移动端自适应问题,请访问最近更新的 rem布局(进阶版)
        http://www.jianshu.com/p/985d26b40199 希望能帮到你。
        梁相辉:@吃葡萄只吃葡萄皮 必须的
      • atfa:回家试试
      • 12da4a727e56:你好:
        能把你例子中的代码 发给我一份吗 (刚入行几天的新手) 1303049692@qq.con
      • chocoling:hello~hello~ 我想问下,这个自适应是自适应width,height,padding。。等等的吧?那字体大小呢?怎么让它自适应啊?
        梁相辉:@JDDB 字体大小同理也用rem做单位呀,比如你的某个标题的字体大小在640宽度下是32px, 设置的时候就可以设为 0.32rem了!
      • be80107fc526:你好,有个疑问。
        就是把设计稿改成640的,然后切图,换算单位的时候直接用设计稿上的宽高除以100,得出rem单位吗?
        还有字体大小也是这样算吗? :flushed:
        梁相辉:@numems 你好,rem布局有重大更新,能更完美解决移动端自适应问题,请访问最近更新的 rem布局(进阶版)
        http://www.jianshu.com/p/985d26b40199 希望能帮到你。
        be80107fc526:@_minooo_ 就是设计稿一定要改成640的吗:flushed:
        梁相辉:@numems 是的,比如你的某个标题的字体大小在640宽度下是32px, 设置的时候就可以设为 0.32rem了!
      • afaabb9f598a:问下楼主 dpi 怎么具体使用呢
        梁相辉:@丁晴晴六耳 你好,请访问最近更新的 rem布局(进阶版)
        http://www.jianshu.com/p/985d26b40199 希望能帮到你。
      • SelfImprovement:方法很好,就是遇到一个问题,页面加载的时候页面会很大,等待页面加载完毕后恢复正常,有没有解决方法呢
        LuckyS007:@SelfImprovement 请问你找到解决方法了吗
        梁相辉:@SelfImprovement 你可以监听window.onload 事件:一开始页面被一个元素全屏遮挡,里面写个loading...,待页面加载完毕(即页面正常时),也就是onload事件触发,把这个遮挡元素隐藏或者删除就可以啦! :blush:
      • 居客侠:我觉得rem还是用在移动端比较好,pc端用媒体查询
        梁相辉:@居客侠 这本来就是用在移动端的呀~
      • 4e5713f86b5b:刷新时会出现闪烁问题,html无法再第一时间显示字号大小
        LuckyS007:@1f233b37461e 直接写死不好吧 有没有其他方法
        安coco:@莎拉_TT 所以直接写死体验还好一些。需要自己计算值
      • 703da61be8b0:图片不能自适应
        梁相辉:@花莳间 img的display设为block
      • 703da61be8b0:按照说明来做,为什么不能自适应?
      • 4ab11bbf43bd:你好,使用这段代码,在跳转链接的时候会出现闪烁的情况,应该如何解决呢?我是使用的media query 加了10行最接近的font-size,但是这种方法仍然不能解决问题,还是会有轻微闪烁。这对于用户来首还是不太完美 。
        LuckyS007:@竹雨清风 你好 请问最后是怎么解决的呢?我也遇到这问题,请赐教
        4e5713f86b5b:@_minooo_ 这个具体要怎么解决?
        梁相辉:@竹雨清风 闪烁的问题应该是样式还没被加载好,你可以设置个loading页面,判断页面如果加载完成再显示。
      • 6a8bfb25874a:你好,只要用rem就不需要添加其它什么的了吗?就可以直接在手机上实现自适应吗
        梁相辉:@康Seven 是的,最好是100吧
        6a8bfb25874a:@随意那天 了解了,只是我可以把初始值设为10px吗,就是10px=1rem。这样子是不是在chrome上面其实初始值是12px=1rem?
        梁相辉:@康Seven 是的,只是这种自适应是一种“等比例缩放”

      本文标题:手机端页面自适应解决方案—rem布局

      本文链接:https://www.haomeiwen.com/subject/upljhttx.html