移动端适配方案-----flexible.js源码、原理

225 阅读2分钟

flexible.js原理

flexible.js 的核心思想是 基于视口宽度动态设置根元素(html)的 font-size,使页面元素通过 rem 单位实现等比缩放。

  • 视口划分:将设备视口宽度(document.documentElement.clientWidth)分为 10 等份,每份为 1rem。例如,视口宽度为 375px 时,1rem = 37.5px。

  • 动态更新:通过监听 resizepageshow 事件,在窗口变化或页面缓存恢复时重新计算 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-scale1/dpr,将 CSS 像素与物理像素对齐。例如,DPR=2 时,缩放比例为 0.5,避免高清屏下元素显示过小。

rem 单位的应用

  • 设计稿转换:设计稿通常以固定宽度(如 750px)制作。开发者将设计稿中的像素值除以基准值(如 75),转换为 rem 单位。例如,设计稿中 150px 的元素对应 2rem(150/75=2)。
  • 自动转换工具:借助 px2rem 等插件,开发阶段可自动将 px 转换为 rem,提升效率。

额外补充,补充完整版flexible.js

juejin.cn/post/740431…

flexible.js 存在问题

  • 自定义配置:配置选项自定义行为,设置不同的基准字体大小等。
  • 性能问题:使用flexible.js可能会引起页面的重排(reflow)和重绘(repaint),影响页面性能。