flexible.js 是移动端的一种使用 rem 适配方案。
源码相对简单,需要知道的前置知识:
- 使用
rem
作为单位,因为rem
是一个相对单位,它相对于根元素的font-size
,页面元素的大小计算都与根元素进行换算。(默认浏览器的大小 16px) window.devicePixelRatio
它将返回当前显示设备的物理像素分辨率与 CSS 像素分辨率之比,也就是设备像素比(DPR)。通过设备屏幕的 DPR,自动设置最合适当前设备的高清缩放。
源码地址。
这里需要解读的代码量相对较少,我直接在代码内进行注释:
;(function flexible(window, document) {
// 获取根元素
var docEl = document.documentElement
// 获取设备像素比
var dpr = window.devicePixelRatio || 1
// 调整 body 字体大小,也就是子元素的默认字体大小都继承自 body
function setBodyFontSize() {
if (document.body) {
document.body.style.fontSize = 12 * dpr + 'px'
} else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize()
// set 1rem = viewWidth / 10
// 也就是 1rem 等于视口/屏幕可视区域宽度的 1/10,将宽度分割为十等分
// 例如:iphone 6 的屏幕宽度为 375px,因此 375 / 10 = 37.5px = 1rem
function setRemUnit() {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// 页面调整时重置 rem
window.addEventListener('resize', setRemUnit)
// pageshow 事件在每次加载页面时触发(包括后退/前进按钮操作,同时也会在 onload 事件触发后初始化页面时触发)
window.addEventListener('pageshow', function (e) {
// persisted 属性表示网页是否是来自缓存
if (e.persisted) {
setRemUnit()
}
})
// 检测是否支持 0.5px,解决 1px 在高清屏多像素问题
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)
相信整体看下来,您已经清楚了 flexible.js 的工作方式。
另外,如果使用到了 rem 适配方案,推荐阅读手机端页面自适应解决方案—rem 布局进阶版(附源码示例)。
推荐阅读一下有关 CSS 单位的知识:CSS 单位及其需要注意的地方。
如今,视口单位已经得到了很好的支持,且能很好的解决横屏问题,比较推荐使用。
以下在推荐几篇移动端适配相关的文章: