一次移动端适配实践 —— rem布局

9,513 阅读3分钟

最近把之前写的 TodoList 小项目重构了一遍。比起之前的版本,重构后的项目改用 Hook,使用 Scss 作为 CSS 预处理器,react-router-dom升级到 V6 版本,同时使用了rem的移动端适配方案。本文就这次重构,总结这次的rem移动端适配实践。

1. 几个概念

1. 物理像素

物理像素又叫设备像素,指的是屏幕上的显示单元,设备实际的像素点,由设备本身的屏幕决定。一个物理像素就是屏幕上一个最小的显示单元,每个显示单元都有自己的颜色和亮度。例如,某屏幕设备在宽度方向有 750 个像素点,高度方向有 1334 个像素点,就代表其真实的显示单元有 750 × 1334 个。

2. 逻辑像素

逻辑像素又叫独立像素,是由程序控制的虚拟像素,在 CSS 样式中,通常说的px就是逻辑像素。描述一张图片大小为100px * 100px,也是逻辑像素的表示。

3. 设备像素比

设备像素比(DPR)就是物理像素逻辑像素的比值,即:

DPR = 物理像素 / 逻辑像素

在相同的屏幕大小下,显示同等逻辑像素的内容,设备像素比越大,则显示的效果越清晰。因为同样的逻辑像素设备像素比较大的,会用更多的物理像素去显示。

2. 移动端适配

1. 方案

TodoList 小项目中,我采用的是移动端适配方案是rem适配。

rem是值相对于根元素<html>字体大小的尺寸单位,如果<HTML>元素没有指定字体尺寸,那么以浏览器默认的字体尺寸为准。例如,<HTML>元素设置了字体尺寸为24px,那么2rem就代表48px

<HTML>元素上设置特定的font-size值,通过媒体查询的方式,若当前设备宽度小于某个值时,采用rem单位的布局。

但是不同用户的设备屏幕宽度不同,若每个用户对应的<HTML>元素font-size值相同的话,用户看到的显示效果也是不同的。

可以用 JavaScript 来根据用户的屏幕宽度,动态更改<HTML>元素上的font-size值,从而使实际显示的内容比例始终保持不变,不同用户看到的效果也会保持一致。

比如,设计稿的宽度为400px,里面显示了一个宽度为40px的盒子。某用户以800px宽度的设备来访问,看到的盒子宽度应该为80px。那么此时在<HTML>元素的font-size值设置为2px,然后盒子的宽度采用rem单位,设置为40rem,那么就能显示出80px的盒子了。保持用户看到的和设计稿中的效果比例一致。

所以,<HTML>元素的font-size计算公式为:

( 用户设备宽度 / 设计稿标准宽度 ) * 100

这里乘以 100 只是一个系数,在写rem的时候,将标准设计稿中的宽度除以 100,就可以转化成了rem单位的宽度。

例如,标准设计稿中某盒子宽度为40px40 / 100 = 0.4,那么移动端适配时,改成0.4rem即可。

2. 实践

在页面下方加这样一段 JavaScript 代码,当 DOM 加载完成时,设置一次<HTML>元素的font-size值。同时监听设备宽度更改,设备宽度变化时,更新<HTML>元素的font-size值。

<script type="text/javascript">
    function inMobile() {
        document.getElementsByTagName('html')[0].style.fontSize =
            (document.documentElement.clientWidth / 450) * 100 + 'px';
    }
    document.addEventListener('DOMContentLoaded', inMobile);
    window.onresize = inMobile;
</script>

样式中的代码,利用媒体查询,当设备宽度小于等于900px时,采用rem布局。否则,采用正常的 PC 端布局。

@media all and (max-width: 900px) {
    .InputBox {
        input {
            width: 100%;
            font-size: 0.24rem;
        }
    }
}

本文是自己学习之拙见,若有不妥,欢迎大佬指出交流~