最近把之前写的 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
宽度的设备来访问,看到的盒子宽度应该为80
px。那么此时在<HTML>
元素的font-size
值设置为2px
,然后盒子的宽度采用rem
单位,设置为40rem
,那么就能显示出80px
的盒子了。保持用户看到的和设计稿中的效果比例一致。
所以,<HTML>
元素的font-size
计算公式为:
( 用户设备宽度 / 设计稿标准宽度 ) * 100
这里乘以 100 只是一个系数,在写rem
的时候,将标准设计稿中的宽度除以 100,就可以转化成了rem
单位的宽度。
例如,标准设计稿中某盒子宽度为40px
,40 / 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;
}
}
}
本文是自己学习之拙见,若有不妥,欢迎大佬指出交流~