怎么通俗易懂理解rem布局

rem布局是现在比较流行的移动端布局,掌握了这种布局方式后,可以很轻易的实现布局自适应手机屏幕。目前淘宝首页就是采用的这种布局方式。

我曾经上网查过很多资料,看过很多解释原理的和使用方法的,可是还是一脸懵逼,可能我是一枚女程序员,脑子转不过来,必须要弄得很清楚透彻才能想明白这个布局的原理。后来我自己在纸上琢磨,用数学公式成功把自己弄明白了。希望也能帮到大家。就像一道数学题一样,见下题:

首先,假设UI给了一张 a(px)的设计稿,手机屏幕宽度为b(px),设置html根元素的字体大小为c(px)。如果现在设计稿上面有个d(px)的元素,那么这个元素在这个手机屏幕上占多少(px)?那么应该设置多少rem呢?

解:设这个元素在手机屏幕上占e(px)

(1)那么元素在设计稿上面的比例和元素在手机屏幕上的比列保持一致,得:d/a=e/b     =>      e=db/a  (px)    

(2)由于手机上html根元素字体为c(px),所以:1(rem)=c(px)。(这是基础知识,不知道的可以自行百度w3c标准)

(3)那么e(px)=e/c(rem)   

(4)把“(1)"得到的e带入”(3)“得:e(px)=db/ac(rem)

(5)这时候,令c=b/a,则e(px)=db/ac(rem)=d(rem)

此时便可得出:当html的font-size为  b/a  (px)的时候,设计稿上的元素为d(px),则在css里面设置为d(rem)

(6)但是由于b/a很可能是小数或者很小的整数,而浏览器页面可设置的最小字体大小为12px,所以可以设置html的font-size为(b/a)*10或者(b/a)*100更合理准确。这里以(b/a)*100为例,如果html的font-size为(b/a)*100,即:c=(b/a)*100,重新带入”(5)“计算得:e(px)=db/ac(rem)=d/100(rem)。

(7)这样就得出结论了:当html字体元素设置为(b/a)*100px时,则在移动端设备上,根据设计稿可以把设计稿上的元素长度除以100便为需要设置的rem。

举例:设计稿为200px,手机屏幕宽为400px,则设置html字体元素为(400/200)*100像素,即:200(px),若设计稿上某个元素宽为96px,则在css里面可以设置为0.96rem,实现了同比缩放或扩大

重点:在搞明白了这个原理后,主要就是怎么设置html的字体大小了。并且是动态设置,(b/a)*100,设计稿固定,则a为固定已知的,主要就是怎么在不同设备上动态获取b(手机屏宽),这里有个js,可以动态计算并设置html的字体,在进入页面的时候加载该js即可(此外如果不用这个js设置,也可以用媒体查询方式设置不用屏宽情况下html的font-size):

js设置方式代码(以设计稿宽为375px举例):

    //designWidth:设计稿的实际宽度值,需要根据实际设置
        (function(designWidth) {
            var doc = document,
                win = window,
                docEl = doc.documentElement,
                remStyle = document.createElement("style"),
                tid;

            function refreshRem() {
                var width = docEl.getBoundingClientRect().width;
                var rem = width * 100 / designWidth;
                remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
            }

            if (docEl.firstElementChild) {
                docEl.firstElementChild.appendChild(remStyle);
            } else {
                var wrap = doc.createElement("div");
                wrap.appendChild(remStyle);
                doc.write(wrap.innerHTML);
                wrap = null;
            }
            //要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
            refreshRem();

            win.addEventListener("resize", function() {
                clearTimeout(tid); //防止执行两次
                tid = setTimeout(refreshRem, 300);
            }, false);

            win.addEventListener("pageshow", function(e) {
                if (e.persisted) { // 浏览器后退的时候重新计算
                    clearTimeout(tid);
                    tid = setTimeout(refreshRem, 300);
                }
            }, false);

            if (doc.readyState === "complete") {
                doc.body.style.fontSize = "16px";
            } else {
                doc.addEventListener("DOMContentLoaded", function(e) {
                    doc.body.style.fontSize = "16px";
                }, false);
            }
        })(375);

 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值