从零到精通前端布局 rem 方案实战总结与优化技巧
又踩坑了,rem方案适配移动端
最近在做一个移动端项目,用到了rem布局方案来适配不同屏幕尺寸。本以为一切会很顺利,结果还是遇到了一些问题。先说说最终的解决方案吧。
核心代码就这几行
首先,我用了以下几行代码来设置rem单位:
(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 750) {
docEl.style.fontSize = '100px';
} else {
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
这个代码的作用是根据屏幕宽度动态调整根元素的字体大小,从而实现rem单位的适配。这里的750是一个基准值,可以根据设计稿的实际宽度进行调整。
折腾了半天发现的问题
在实际开发中,我发现了一些问题。首先是有些设备在旋转屏幕时,rem单位没有及时更新,导致布局错乱。后来试了下发现,监听orientationchange事件可以解决这个问题。
另外,我还遇到一个问题,就是某些设备(尤其是Android)在切换横竖屏时,clientWidth可能会返回不准确的值。这里我踩了个坑,折腾了半天发现可以在recalc函数中加一个延时,确保获取到正确的宽度。
var recalc = function () {
setTimeout(function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 750) {
docEl.style.fontSize = '100px';
} else {
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
}
}, 300);
};
这样就能确保在屏幕旋转后,rem单位能正确更新。不过,这样也有个小问题,就是在快速旋转屏幕时,可能会出现短暂的布局错乱。好在这个问题影响不大,无大碍。
为什么选择rem方案
说了这么多,你可能想知道我为什么选择rem方案。其实原因很简单,rem方案相比其他布局方案有几个明显的优势:
- 灵活性高:通过改变根元素的字体大小,可以轻松实现不同屏幕尺寸的适配。
- 易于维护:只需要在根元素上设置一次字体大小,就可以在整个项目中使用rem单位,减少了代码量。
- 兼容性好:rem单位在现代浏览器中的支持非常好,几乎不需要额外的处理。
当然,rem方案也有一些缺点,比如在某些情况下可能会出现小数点问题,导致布局不精确。但这些问题通常可以通过一些简单的技巧来解决,比如使用calc()函数。
技术细节和原理
rem单位是相对于根元素(即<html>标签)的字体大小来计算的。例如,如果根元素的字体大小是16px,那么1rem就等于16px。这种相对单位的好处是,当我们改变根元素的字体大小时,所有使用rem单位的元素都会相应地调整。
在上面的代码中,我们通过监听窗口的resize事件和orientationchange事件来动态调整根元素的字体大小。具体来说,当屏幕宽度小于750px时,根元素的字体大小会被设置为100 * (clientWidth / 750) + 'px',这样可以确保在不同屏幕尺寸下的布局一致。
这里还有一个小技巧,就是将基准值设为750px。这个值并不是固定的,可以根据设计稿的实际宽度进行调整。例如,如果设计稿的宽度是375px,那么可以将基准值设为375px,这样可以更方便地进行像素转换。
最后总结一下
以上是我个人对rem方案的一些实战经验和总结。虽然过程中遇到了一些坑,但总体来说,rem方案还是非常实用和灵活的。如果你有更好的方案或建议,欢迎在评论区交流。
这个技巧的拓展用法还有很多,后续我会继续分享这类博客。希望这些经验对你有所帮助。
