rem.js的技术实现原理是怎样的?rem.js的N种写法
发布于 作者:苏南大叔 来源:程序如此灵动~刚刚说了px
转rem
的事情,现在苏南大叔来解析一下配套的rem.js
如何使用。在开始本文之前,苏南大叔要说的是:rem.js
的基本原理是比较简单的,而且业界也没有形成统一的标准答案。所以,rem.js
也是百花齐放状态。本文中列举几个rem.js
的写法,大家看着喜欢哪个,就用哪个吧。
注意:一般是在移动端适配环境下面使用这个rem
系统的。所以,如果您编写的是传统的pc
网页,请转身查看苏南大叔的其他文章。本文中,如非特殊说明,本文的默认的设计稿宽度750px
,默认的font-size
为100px
,通过rem.js
计算后的font-size
就不一定了,多少都有可能。本文测试环境:win10
,chrome@ 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)
};
写法二(据说来自小米)
这里也有750
和100
的字样,注意替换。
!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.js
在head
区执行吗?如果能,恭喜您,可以试试。如果不能,那么页面闪动的话,别四处抓瞎哦。(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
里面设定,比如:设计稿宽度,html
的font-size
。需要和css
里面的换算设定保持一致!rem.js
最好配合好meta
的viewport
,需要在head
区域生成。rem.js
需要在页面resize
的时候,重新设置html
的font-size
。
相关链接
总结
rem.js
说简单就简单,说难就难。整体来说,应该是要被更合理的技术所取代的。至于新的继任者是谁,大家可以拭目以待。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。