基于 rem 的前端布局方案
2020-04-29 · 635 chars · 4 min read
本文很简单,分享一下我们目前使用的 rem 布局方案,大体的思路和之前社区里的其他方案基本一致,但是在实际使用中发现不少问题,逐渐演变成了今天的模样。
目前这套方案大体上是比较稳定的,可能日后随着设备的更新、迭代、升级,vw 等新方案会越来越普及,布局也就不会像现在这么麻烦了。
Note
演变过程中的问题大多比较琐碎和细节,受迫于整体开发进度比较紧张,部分兼容性问题没有记录下来,没有查清楚原因...
代码#
;(function (doc, win) { var docEl = doc.documentElement var resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize' /** * 不管 fontsize 是多少,直接通过 clientWidth 对比 * * 直接对比 fontsize 在 android webview 79+ 有问题 * 问题表现是: * 有时设置 html font-size 16px,获取到是 20px,但是 rem 依然根据 16px 计算; * 一加 7t 上更加奇怪,具体表现待查; */ var getClientWidthWithRem = function () { var $div = doc.createElement('div') $div.style.width = '3.75rem' $div.style.visibility = 'hidden' doc.head.appendChild($div) var width = parseFloat(win.getComputedStyle($div).width) doc.head.removeChild($div) return width } var recalc = function (event) { var clientWidth = docEl.clientWidth /** * 设备宽度大于 640px,fontSize 统一取上限值 */ if (clientWidth >= 640) { docEl.style.fontSize = (640 / 375) * 100 + 'px' return } /** * 传统 rem 方案 */ var fontSize = (clientWidth / 375) * 100 docEl.style.fontSize = fontSize + 'px' /** * 再次校验,处理用户调整了系统字体大小的情况 */ var currentClientWidth = getClientWidthWithRem() if (Math.abs(currentClientWidth - clientWidth) > 1) { docEl.style.fontSize = fontSize * (clientWidth / currentClientWidth) + 'px' } } recalc() if (!doc.addEventListener) { return } win.addEventListener(resizeEvt, recalc, false) doc.addEventListener('DOMContentLoaded', recalc, false) })(document, window)
使用前提#
- 我们团队的视觉规范是宽 375,所以代码全部是按照 375 换算的,这是唯一前提。如果和你们的视觉规范不一致,调整计算规则即可
- 我们给 H5 限制了最大宽度 640,一定程度上保证了页面在 PC 浏览器上的体验,这里大家自行酌情调整
使用方式#
- 将代码压缩后插入
<head>
(可以使用 terser 压缩),不建议外链,关键渲染路径优化 - 而后,所有尺寸除以 100,加单位 rem 即可。例如一个图片在视觉稿上宽 200,代码里写
2rem
即可 - 一些如 1px 边框的问题,直接 transform 缩放即可
- 字体看情况处理,用 rem 和 px 都可以,主要还是看规范