移动端适配
1 名词定义
-
设备物理像素 (Device Physical Pixels)
-
定义:设备屏幕上最小的物理显示单元,也就是我们常说的“像素点”。每个像素点由红、绿、蓝子像素组成。
-
特点:是硬件的固有属性,出厂时固定,无法改变。
-
例子:iPhone 12 的屏幕有 2532 x 1170 个物理像素点。
-
-
设备像素比 (Device Pixel Ratio, DPR)
-
定义:一个设备物理像素与设备独立像素(逻辑像素)之间的比例关系。公式为:DPR = 物理像素 / 逻辑像素(在同一方向上)。
-
作用:描述了屏幕的密度(清晰度)。DPR 越高,屏幕越清晰。
-
例子:iPhone 12 的 DPR 为 3,意味着在水平方向上,1 个设备独立像素(逻辑像素)由 3 个物理像素来渲染。
-
-
设备独立像素 (Device Independent Pixels, DIPs) / 逻辑像素 (Logical Pixels)
-
定义:一种由软件定义的像素单位,用于抽象不同物理像素密度的设备,使得应用程序和网页在不同设备上有一致的视觉大小。
-
特点:与设备物理像素无关,由操作系统管理。在同一个操作系统中,设备独立像素(逻辑像素)的大小是固定的(例如,1 逻辑像素约等于 1/160 英寸)。
-
例子:iPhone 12 的逻辑分辨率为 390 x 844 逻辑像素。
-
-
逻辑分辨率 (Logical Resolution)
-
定义:用逻辑像素表示的屏幕分辨率,即屏幕在逻辑像素尺寸上的宽高。
-
子:iPhone 12 的逻辑分辨率为 390 x 844。
-
-
CSS 像素 (CSS Pixels)
-
定义:在 CSS 和 Web 开发中使用的抽象单位。我们编写 CSS 时使用的 px 单位就是 CSS 像素。
-
特点:在默认情况下(即未进行移动端适配时),1 个 CSS 像素对应 1 个设备独立像素(逻辑像素)。但是,当用户进行缩放时,CSS 像素会发生变化(例如放大时,1 个 CSS 像素会占用多个设备独立像素)。
-
与逻辑像素的关系:在理想视口(ideal viewport)下,1 CSS 像素 = 1 设备独立像素(逻辑像素)
-
-
物理分辨率 (Physical Resolution)
-
定义:用设备物理像素表示的屏幕分辨率,即屏幕在物理像素尺寸上的宽高。
-
例子:iPhone 12 的物理分辨率为 2532 x 1170 物理像素。
-
2 关系梳理
设备物理像素和物理分辨率是硬件层面的概念,描述了屏幕实际的像素点数量。
设备独立像素(逻辑像素)和逻辑分辨率是软件层面的概念,由操作系统定义,目的是统一不同密度设备上的尺寸度量。
设备像素比(DPR) 是连接物理像素和逻辑像素的桥梁:物理像素 = 逻辑像素 × DPR。
CSS 像素是 Web 开发中的单位,在默认情况下与逻辑像素等价,但可以通过 viewport 缩放、CSS 变换等操作改变其实际占用的物理像素。
举例说明(以 iPhone 12 为例)
物理分辨率:2532 x 1170(物理像素)
逻辑分辨率:390 x 844(逻辑像素)
DPR:3(因为 1170 / 390 = 3,2532 / 844 ≈ 3)
CSS 像素:在理想视口下,1 CSS 像素 = 1 逻辑像素,所以一个宽度为 390 CSS 像素的元素将刚好充满 iPhone 12 的屏幕宽度。
3 为什么要有这些概念?
主要是为了应对不同屏幕密度的设备。如果直接使用物理像素,那么在高密度屏幕上(如 DPR=3),网页上的元素会显得非常小(因为物理像素点非常密集)。通过引入逻辑像素,操作系统和浏览器可以提供一个统一的尺度,使得同样大小的 CSS 元素在不同密度的屏幕上看起来物理大小相近。
通过引入设备独立像素(逻辑像素)和 DPR:
- 开发者始终面对统一的逻辑尺寸(如 375px 宽度)
- 操作系统/浏览器根据 DPR 自动选择用更多物理像素来渲染,实现高清显示
4 移动端适配的意义
移动端适配的核心就是让网页在不同逻辑分辨率(即不同设备宽度)下都能良好显示。我们通过 viewport 设置和 CSS 媒体查询、相对单位(如 rem、vw)等,使页面布局根据逻辑分辨率(CSS 像素)自适应调整。
5 示意图
6 对移动端适配的理解
6.1 前提条件:
-
设计稿尺寸为 375*667,有一个元素,元素的尺寸为 10px*10px
-
设置了理想视口,即此时 1 CSS 像素 = 1 设备独立像素
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
6.2 设备信息
| 信息 | iPhoneSE | iPhone12 |
|---|---|---|
| 设备物理像素 | 750*1334 | 1170*2532 |
| 设备独立像素 | 375*667 | 390*844 |
| DPR | 2 | 3 |
| 1rem | 375/10 = 37.5px | 390/10 = 39px |
6.3 适配思路
移动端适配的最终目的就是:保持元素尺寸与视口宽度的相对比例恒定,从而在不同设备上还原一致的视觉关系和布局意图
首先我们不进行适配,直接使用 px,根据设计稿,我们编写下方的样式:
.block {
width: 10px;
height: 10px;
background: red;
}
我们计算一下比例,计算如下:
在iPhoneSE上
10 / 375 = 0.02666666666666667
在iPhone12上
10 / 390 = 0.02564102564102564
可以看到,元素宽度/设备独立像素的比例是不一致的,这样就导致了页面效果的不一致,看起来就会不协调
接下来,我们采用 rem 进行移动端适配,目的是为了让同一个元素在不同设备上的比例(元素宽度/设备独立像素宽度)一致
根据设计稿的尺寸,我们有以下计算:
1rem = 375 / 10 = 37.5px
1px = 0.02666666666rem;
样式如下:
.block {
width: 0.266666rem;
height: 0.266666rem;
background: red;
}
此时我们再计算比例,计算如下:
在iPhoneSE上
0.266666 * 37.5 = 9.99997
9.99997 / 375 = 0.026666586666666665
在iPhone12上
0.266666 * 39 = 10.399974
10.399974 / 390 = 0.026666600000000002
可以看到,使用 rem 进行移动端适配,再换算为 px 之后,不同设备上,元素宽度/设备独立像素宽度的比例是一致的,这样看起来就是协调的
7 移动端 Rem 适配方案代码
这里以 Vue 项目为例,详细介绍如何实现 rem 适配
7.1 安装相关依赖
"postcss": "^8.5.6",
"postcss-pxtorem": "^6.1.0",
7.2 创建 postcss.config.cjs 文件
在项目根目录下,与 src 目录同级,新增 postcss.config.cjs 文件,文件内容如下
module.exports = {
plugins: {
"postcss-pxtorem": {
// 设计稿宽度/10,即750px设计稿 -> 75
rootValue: 75,
// 转换所有属性的单位
propList: ["*"],
// 忽略带有'no-rem-[className]'类的元素,这些元素内的px不转换
// 如 <div class="no-rem-block"></div> 则 .no-rem-block 中的样式都不会进行转换
selectorBlackList: ["no-rem"],
},
},
};
7.3 创建并引入 adaptation.js 文件
创建 adaptation.js 文件,并且在 src/main.js 当中引入此文件
/**
* 移动端适配
* 以设计稿750px为例,将布局视口分成10份,则1rem=75px
* 例如在375px宽的设备上,html的font-size就是 375px / 10 = 37.5px
*/
(function (doc, win) {
const docEl = doc.documentElement;
const resizeEvt = "orientationchange" in window ? "orientationchange" : "resize";
const recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
docEl.style.fontSize = clientWidth / 10 + "px";
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener("DOMContentLoaded", recalc, false);
})(document, window);
7.4 使用
/* 在文件当中直接使用px作为单位,postcss会自动编译为rem */
.block {
width: 100px;
height: 100px;
background-color: red;
}
8 移动端图片模糊问题
前提条件:
-
设置了理想视口,即 1CSS 像素 = 1 设备独立像素
-
图片的尺寸为 200 * 200
-
HTML 页面当中设置图片的样式
.bg-img { width: 100px; height: 100px; }
在 DPR 为 2 的设备上,这个图片是清晰的,因为 1 CSS 像素 = 1 设备独立像素 = 2 设备物理像素,100px = 200 设备物理像素,相当于把 200 物理像素的图片,放到 200 设备物理像素的区域里面,刚好放得下
假如把上面的这个图片,放在 DPR 为 3 的设备上,此时 1 CSS 像素 = 1 设备独立像素 = 3 设备物理像素,100px = 300 设备物理像素,也就是 200 物理像素的图片,要放在 300 物理像素的区域里面,想要占满区域,就需要放大这个图片,也就导致了图片模糊