说说设备像素、CSS 像素、设备独立像素、dpr、ppi 之间的区别
问题解析
随着移动设备和视网膜屏幕的普及,理解像素相关的概念变得至关重要。面试考察这个问题,是想要了解候选人对移动端适配、高清屏处理等实际问题的理解深度。
核心概念
1. 设备像素(Device Pixel)
物理像素,是屏幕能控制显示的最小物理单位。
- 从屏幕生产出来就固定不变
- 单位为
pt(point) - iPhone 4 之前,1 CSS 像素 = 1 设备像素
2. CSS 像素(CSS Pixel)
逻辑像素,Web 开发中使用的抽象单位,用 px 表示。
- 是相对单位,不是绝对的物理尺寸
- 同一设备上,受缩放比例影响
- 不同设备上,受 DPR 影响
缩放比例 1:1 → 1 CSS 像素 = 1 设备像素
缩放比例 2:1 → 1 CSS 像素 = 4 设备像素(2×2)
3. 设备独立像素(Device Independent Pixel, DIP)
逻辑像素单位,与设备无关。
- 是 CSS 像素的基础
- JavaScript 中
window.screen.width/height获取的就是 DIP - 在标准屏幕(160ppi)下,1 DIP = 1 设备像素
4. 设备像素比(DPR, Device Pixel Ratio)
设备像素与设备独立像素的比值。
DPR = 设备像素 / 设备独立像素
常见设备 DPR:
| 设备 | DPR |
|---|---|
| 普通桌面显示器 | 1 |
| iPhone 3GS | 1 |
| iPhone 4/5/6/7/8 | 2 |
| iPhone X/11/12/13/14 | 3 |
| Android 高清屏 | 2-4 |
JavaScript 获取:
window.devicePixelRatio; // 返回 DPR,如 2 或 3
5. 每英寸像素(PPI, Pixels Per Inch)
每英寸包含的物理像素数,表示屏幕密度。
PPI = √(横向像素² + 纵向像素²) / 屏幕对角线英寸数
常见分类:
| 类别 | PPI 范围 |
|---|---|
| 标准密度(mdpi) | ~160 |
| 高密度(hdpi) | ~240 |
| 超高密度(xhdpi) | ~320 |
| 超超高密度(xxhdpi) | ~480 |
| 超超超高密度(xxxhdpi) | ~640 |
关系图解
┌─────────────────────────────────────────┐
│ 设备(如 iPhone 14) │
│ 屏幕分辨率:1170 × 2532(设备像素) │
│ 屏幕尺寸:6.1 英寸 │
│ DPR:3 │
│ │
│ 计算: │
│ 设备独立像素 = 1170/3 × 2532/3 │
│ = 390 × 844 │
│ │
│ CSS 中 width: 390px 将占满屏幕宽度 │
└─────────────────────────────────────────┘
深入理解
为什么需要设备独立像素
假设没有 DIP:
| 设备 | 物理分辨率 | 按钮设置 width: 100px |
|---|---|---|
| iPhone 3GS | 320×480 | 占 1/3 屏宽,合适 |
| iPhone 14 | 1170×2532 | 占 1/11 屏宽,太小 |
使用 DIP 统一为 390 逻辑宽度后:
- iPhone 3GS:100px 按钮 → 100 物理像素
- iPhone 14:100px 按钮 → 300 物理像素(自动放大)
DPR 对开发的影响
1. 高清图片
/* DPR=2 的设备需要 2x 图 */
/* DPR=3 的设备需要 3x 图 */
/* srcset 方案 */
<img src="image-1x.png"
srcset="image-2x.png 2x, image-3x.png 3x"
alt="响应式图片">
2. 1px 边框问题
在 DPR=2 的设备上,1 CSS 像素的边框实际是 2 物理像素,看起来更粗。
/* 解决方案:使用 transform 缩放 */
.border-1px {
position: relative;
}
.border-1px::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 1px;
background: #ccc;
transform: scaleY(0.5); /* DPR=2 时 */
transform-origin: 0 0;
}
/* 适配不同 DPR */
@media (-webkit-min-device-pixel-ratio: 2) {
.border-1px::after {
transform: scaleY(0.5);
}
}
@media (-webkit-min-device-pixel-ratio: 3) {
.border-1px::after {
transform: scaleY(0.333);
}
}
3. Canvas 绘制
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const dpr = window.devicePixelRatio || 1;
// 设置显示大小
const width = 300;
const height = 150;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
// 设置实际渲染大小(放大 DPR 倍)
canvas.width = width * dpr;
canvas.height = height * dpr;
// 缩放画布
ctx.scale(dpr, dpr);
// 现在按正常逻辑绘制,会自动高清
ctx.fillRect(10, 10, 100, 100);
移动端适配方案
1. rem 方案
function setRem() {
const width = document.documentElement.clientWidth;
document.documentElement.style.fontSize = (width / 10) + 'px';
}
// 1rem = 视口宽度的 1/10
2. vw 方案
.element {
width: 50vw; /* 视口宽度的 50% */
font-size: 2vw; /* 视口宽度的 2% */
}
3. viewport 缩放方案
<script>
// 动态设置 viewport scale
var dpr = window.devicePixelRatio;
var scale = 1 / dpr;
var meta = document.createElement('meta');
meta.name = 'viewport';
meta.content = 'width=device-width, initial-scale=' + scale + ', maximum-scale=' + scale;
document.head.appendChild(meta);
</script>
常见问题
1px 细线问题
/* 最佳实践 */
.hairline {
position: relative;
}
.hairline::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: #e5e5e5;
transform: scaleY(0.5);
transform-origin: 0 100%;
}
高清屏图片模糊
/* 使用 2x/3x 图片 */
.image {
background-image: url(image@1x.png);
}
@media (-webkit-min-device-pixel-ratio: 2) {
.image {
background-image: url(image@2x.png);
}
}
@media (-webkit-min-device-pixel-ratio: 3) {
.image {
background-image: url(image@3x.png);
}
}
总结对比
| 概念 | 英文 | 说明 |
|---|---|---|
| 设备像素 | Device Pixel | 物理像素,屏幕实际发光点 |
| CSS 像素 | CSS Pixel | 逻辑像素,开发使用的单位 |
| 设备独立像素 | DIP | 逻辑像素基准,与设备无关 |
| 设备像素比 | DPR | 设备像素 / 设备独立像素 |
| 每英寸像素 | PPI | 屏幕密度指标 |
面试要点
- 能够清晰区分设备像素、CSS 像素、设备独立像素
- 理解 DPR 的概念和计算方法
- 知道如何在不同 DPR 下处理 1px 边框问题
- 了解高清图片的适配方案(srcset、媒体查询)
- 能够说出 rem/vw 等移动端适配方案的原理
- 了解 Canvas 在高清屏上的绘制技巧