我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

刚刚说了pxrem的事情,现在苏南大叔来解析一下配套的rem.js如何使用。在开始本文之前,苏南大叔要说的是:rem.js的基本原理是比较简单的,而且业界也没有形成统一的标准答案。所以,rem.js也是百花齐放状态。本文中列举几个rem.js的写法,大家看着喜欢哪个,就用哪个吧。

苏南大叔:rem.js的技术实现原理是怎样的?rem.js的N种写法 - remjs-hero
rem.js的技术实现原理是怎样的?rem.js的N种写法(图2-1)

注意:一般是在移动端适配环境下面使用这个rem系统的。所以,如果您编写的是传统的pc网页,请转身查看苏南大叔的其他文章。本文中,如非特殊说明,本文的默认的设计稿宽度750px,默认的font-size100px,通过rem.js计算后的font-size就不一定了,多少都有可能。本文测试环境:win10chrome@ 83.0.4103.61

rem.js基本原理

rem.js基本原理就是:动态修改html标签的样式中的font-size(单位是px)。例如:

html{font-size:100px;}

但是,大厂的p8程序员们,会继续修改meta中的viewport。所以,部分版本的rem.js还需要在rem.js之前,有个下面类似的html语句:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

所以,最标准的写法是这样的:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="rem.js"></script>
</head>
<body>
    
</body>
</html>

接下来介绍,rem.js的N种写法。大家选择一个你喜欢的rem.js即可。

方案一:最简单的写法

这里不做特别的评述了,大家自己看着用。代码来源于网络,这里向原作者表示感谢。

function getRem(design_w, unit) {
    var html = document.getElementsByTagName("html")[0];
    var real_w = document.documentElement.clientWidth;
    (real_w > design_w) && (real_w = design_w);
    html.style.fontSize = real_w / design_w * unit + "px";
}
getRem(750, 100);
//window.addEventListener("resize",getRem);
window.onresize = function () {
    getRem(750, 100)
};

苏南大叔:rem.js的技术实现原理是怎样的?rem.js的N种写法 - 1rem-what-px
rem.js的技术实现原理是怎样的?rem.js的N种写法(图2-2)

写法二(据说来自小米)

这里也有750100的字样,注意替换。

!function(n){
    var  e=n.document,
         t=e.documentElement,
         i=750,
         d=i/100,
         o="orientationchange"in n?"orientationchange":"resize",
         a=function(){
             var n=t.clientWidth||320;n>750&&(n=750);
             t.style.fontSize=n/d+"px"
         };
         e.addEventListener&&(n.addEventListener(o,a,!1),e.addEventListener("DOMContentLoaded",a,!1))
}(window);

写法三

这个方案,来自于曾经的王者flexible.js

不过,鉴于官方的态度,是已经废弃。大家可以点击下面的地址,查看经典版本(0.3.2)的使用方法。

flexible.js有个论断,就是这些代码,最终都要归结于viewport方案。

写法四

本写法,请在使用前,请阅读代码。明白参数设置!原文链接:

;(function (designWidth, maxWidth) {
    var doc = document,
        win = window;
    var docEl = doc.documentElement;
    var tid;
    var rootItem, rootStyle;

    function refreshRem() {
        var width = docEl.getBoundingClientRect().width;
        if (!maxWidth) {
            maxWidth = 540;
        }
        if (width > maxWidth) {
            width = maxWidth;
        }
        //与淘宝做法不同,直接采用简单的rem换算方法1rem=100px
        var rem = width * 100 / designWidth;
        //兼容UC开始
        rootStyle = "html{font-size:" + rem + 'px !important}';
        rootItem = document.getElementById('rootsize') || document.createElement("style");
        if (!document.getElementById('rootsize')) {
            document.getElementsByTagName("head")[0].appendChild(rootItem);
            rootItem.id = 'rootsize';
        }
        if (rootItem.styleSheet) {
            rootItem.styleSheet.disabled || (rootItem.styleSheet.cssText = rootStyle)
        } else {
            try {
                rootItem.innerHTML = rootStyle
            } catch (f) {
                rootItem.innerText = rootStyle
            }
        }
        //兼容UC结束
        docEl.style.fontSize = rem + "px";
    };
    refreshRem();

    win.addEventListener("resize", function () {
        clearTimeout(tid); //防止执行两次
        tid = setT imeout(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, 750);

写法五,适合编译类型的写法

在这里,苏南大叔就说一句话,您能保证这个rem.jshead区执行吗?如果能,恭喜您,可以试试。如果不能,那么页面闪动的话,别四处抓瞎哦。(webpack等处理这些js,一般都是放在body底部的)
rem.js:

export function setRemInit() {
  // 当前页面宽度相对于 750 px(设计稿尺寸)的缩放比例。
  // const baseSize = 100; // postcss-px2rem的内容
  function setRem(designWidth,baseSize) {
    const scale = document.documentElement.clientWidth / designWidth;
    document.documentElement.style.fontSize = '${baseSize * scale}px';
    /*
    if (Number(document.documentElement.style.fontSize.slice(0, -2)) <= 50) {
       document.documentElement.style.fontSize = '50px';
    }
    */
  }
  setRem(750,100);
  window.addEventListener('resize', function(){setRem(750,100);});
}

main.js:

import { setRemInit } from '@/rem.js';
setRemInit(); 

注意事项

  • rem.js里面设定,比如:设计稿宽度,htmlfont-size。需要和css里面的换算设定保持一致!
  • rem.js最好配合好metaviewport,需要在head区域生成。
  • rem.js需要在页面resize的时候,重新设置htmlfont-size

相关链接

总结

rem.js说简单就简单,说难就难。整体来说,应该是要被更合理的技术所取代的。至于新的继任者是谁,大家可以拭目以待。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   rem