flexible.js原理
flexible.js 的核心思想是 基于视口宽度动态设置根元素(html)的 font-size,使页面元素通过 rem 单位实现等比缩放。
-
视口划分:将设备视口宽度(
document.documentElement.clientWidth)分为 10 等份,每份为 1rem。例如,视口宽度为 375px 时,1rem = 37.5px。 -
动态更新:通过监听
resize和pageshow事件,在窗口变化或页面缓存恢复时重新计算 font-size,确保响应式适配。
flexile.js源码
flexible.js 通过立即执行函数初始化,主要包含以下模块:
// 首先是一个立即执行函数,执行时传入的参数是window和document
(function flexible (window, document) {
var docEl = document.documentElement // 返回文档的root元素
var dpr = window.devicePixelRatio || 1 // 获取设备的dpr,即当前设置下物理像素与虚拟像素的比值
// adjust body font size 设置默认字体大小,默认的字体大小继承自body
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// 当页面展示或重新设置大小的时候,触发重新
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports 检测是否支持0.5像素,
// 解决1px在高清屏多像素问题,需要css的配合。
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
关键代码解析
- DPR 获取与缩放设置:通过
window.devicePixelRatio获取 DPR,动态设置 viewport 的缩放比例,解决高清屏显示问题。 - rem 动态计算:
docEl.clientWidth / 10将视口宽度分为 10 份,确保 rem 基准值随设备宽度变化。 - 0.5px 边框支持:通过创建测试元素检测浏览器是否支持 0.5px 边框,添加
hairlines类优化高清屏下的 1px 显示效果。
设备像素比(DPR)与 viewport 缩放
- DPR 的作用:DPR(Device Pixel Ratio)表示物理像素与 CSS 像素的比值。例如,iPhone 6 的 DPR 为 2,意味着 1 个 CSS 像素对应 2×2 物理像素。
- viewport 缩放:flexible.js 通过设置
<meta name="viewport">的initial-scale为1/dpr,将 CSS 像素与物理像素对齐。例如,DPR=2 时,缩放比例为 0.5,避免高清屏下元素显示过小。
rem 单位的应用
- 设计稿转换:设计稿通常以固定宽度(如 750px)制作。开发者将设计稿中的像素值除以基准值(如 75),转换为 rem 单位。例如,设计稿中 150px 的元素对应 2rem(150/75=2)。
- 自动转换工具:借助
px2rem等插件,开发阶段可自动将 px 转换为 rem,提升效率。
额外补充,补充完整版flexible.js
flexible.js 存在问题
- 自定义配置:配置选项自定义行为,设置不同的基准字体大小等。
- 性能问题:使用
flexible.js可能会引起页面的重排(reflow)和重绘(repaint),影响页面性能。