前言:
之前在项目中引入 flexible.js 这个包,并在vite脚手架中安装了 postCssPxToRem 这个打包插件后,我的H5项目就能根据屏幕宽度缩放,自动调整页面上所有UI元素的大小。这非常神奇。所以我决定探究一下其原理。
-
打包阶段:
postCssPxToRem插件用于将CSS中的PX转换为REM。
那么我们如何指定,40px该转换为多少Rem呢?
这就用到了postCaaPxToRem插件的 “rootValue” 属性。
举例,这里我们将rootValue设为41.4,这里的语义是:“打包代码时,我们假定1Rem等于41.4px”
所以,在以下的配置下,40px会被转换为40 / 41.4 = 0.966183rempostCssPxToRem({ rootValue: 41.4, propList: ["*"], })
现在我们打包出来的代码,所有的UI元素都是以REM为单位的了。
-
浏览器运行阶段:
在实际浏览器代码执行中,REM这个单位实际上是 “Font size of the root element.”
意思就是说:n Rem 就是 n * 根元素的font-size
这套方案效果是,我们在缩小屏幕宽度的时候,把UI元素等比例缩小。
所以,我们只需要监听window的“resize“事件,在resize发生时,获取当前window的宽度,并根据window的宽度重新计算并设定根元素的font-size。此时,因为页面上所有UI元素都以“REM“为单位,我们一旦手动重新设定根元素的”font-size“,那么就改变了整个页面上所有的UI大小。实现了响应式缩放。
下面是flexible.js监听window resize并重新设定根元素font-size的的核心代码:
win.addEventListener( 'resize', function () { clearTimeout(tid); tid = setTimeout(refreshRem, 300); }, false, ); function refreshRem() { var width = docEl.getBoundingClientRect().width; // 设计稿为414,计算rem最大宽度不能大于414 if (width / dpr > 414) { width = 414 * dpr; } var rem = width / 10; docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; }
-
参考文献:
CSS values and units - Learn web development | MDN (mozilla.org) 介绍了REM单位的定义