一、flexible.js 的核心原理
1. 动态 rem 基准值的计算
flexible.js 的核心思想是 基于视口宽度动态设置根元素(html)的 font-size,使页面元素通过 rem 单位实现等比缩放。具体步骤如下:
- 视口划分:将设备视口宽度(
document.documentElement.clientWidth)分为 10 等份,每份为 1rem。例如,视口宽度为 375px 时,1rem = 37.5px。 - 动态更新:通过监听
resize和pageshow事件,在窗口变化或页面缓存恢复时重新计算 font-size,确保响应式适配。
2. 设备像素比(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,避免高清屏下元素显示过小。
3. rem 单位的应用
- 设计稿转换:设计稿通常以固定宽度(如 750px)制作。开发者将设计稿中的像素值除以基准值(如 75),转换为 rem 单位。例如,设计稿中 150px 的元素对应 2rem(150/75=2)。
- 自动转换工具:借助
px2rem等插件,开发阶段可自动将 px 转换为 rem,提升效率。
二、flexible.js 的代码实现解析
1. 代码结构概览
flexible.js 通过立即执行函数初始化,主要包含以下模块:
(function flexible(window, document) {
// 获取根元素与 DPR
var docEl = document.documentElement;
var dpr = window.devicePixelRatio || 1;
// 设置 body 字体大小
function setBodyFontSize() { /* ... */ }
// 计算并设置 rem 基准值
function setRemUnit() {
var rem = docEl.clientWidth / 10;
docEl.style.fontSize = rem + 'px';
}
// 监听窗口变化
window.addEventListener('resize', setRemUnit);
// 处理 0.5px 边框支持
if (dpr >= 2) { /* ... */ }
})(window, document);
2. 关键代码解析
- DPR 获取与缩放设置:通过
window.devicePixelRatio获取 DPR,动态设置 viewport 的缩放比例,解决高清屏显示问题。 - rem 动态计算:
docEl.clientWidth / 10将视口宽度分为 10 份,确保 rem 基准值随设备宽度变化。 - 0.5px 边框支持:通过创建测试元素检测浏览器是否支持 0.5px 边框,添加
hairlines类优化高清屏下的 1px 显示效果。
三、flexible.js 的适配优势与局限性
1. 优势分析
- 流式布局:通过 rem 实现元素等比缩放,适配不同屏幕尺寸。
- 高清显示:结合 DPR 调整 viewport 缩放,解决 Retina 屏下的图片模糊与边框过粗问题。
- 开发便捷:配合自动化工具(如 px2rem),减少手动计算成本。
2. 局限性
- 维护性下降:需依赖 JavaScript 动态计算,增加运行时开销。
- 兼容性问题:部分第三方库(如高德地图)可能因 viewport 缩放导致显示异常,需特殊处理。
- 现代方案替代:CSS3 的
vw/vh单位及postcss插件逐渐成为更轻量的替代方案。
四、flexible.js 的实际应用与优化
1. 设计稿与开发流程
- 设计稿基准:通常以 750px(二倍图)为标准,1rem=75px,简化计算。
- 工具链集成:使用 Webpack 的
px2rem-loader或 Gulp 的gulp-px3rem实现自动转换。
2. 常见问题与解决方案
- 第三方组件适配:如高德地图因 viewport 缩放显示异常时,可通过临时重置 viewport 的
initial-scale解决。 - 字体大小调整:设置
body的font-size为12 * dpr,避免 rem 单位导致字体过小。
五、与其他适配方案的对比
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 媒体查询 | 根据设备特性应用不同 CSS 规则 | 简单直观 | 代码冗余,维护成本高 |
| 百分比布局 | 相对父元素尺寸定义元素大小 | 无依赖 JavaScript | 嵌套复杂时计算困难 |
| flexible.js | 动态 rem + viewport 缩放 | 自适应性强,支持高清屏 | 依赖 JS,需处理第三方兼容性 |
| vw/vh | 基于视口宽高的 CSS 单位 | 纯 CSS 实现,无运行时开销 | 兼容性需处理(IE9 以下不支持) |