DPR (Device Pixel Ratio 设备像素比)
在现代前端和跨端(小程序/App)开发中,屏幕适配是一个绕不开的话题。而这一切的核心,都建立在一个概念之上:DPR (Device Pixel Ratio)。
什么是 DPR
DPR (设备像素比) 是默认缩放为 100% 的情况下,设备物理像素和逻辑像素的比例。
简单来说,它表示了操作系统在一个方向上(宽度或高度),用多少个真实的屏幕发光点,来渲染一个代码里写的 CSS 像素。
计算公式:
DPR = 物理像素 (Physical Pixels) / 逻辑像素 (Logical Pixels)
核心概念解析
要真正理解 DPR,必须先搞清楚它等式右边的两个“像素”:
物理像素 (Physical Pixel / Device Pixel)
- 本质: 屏幕硬件上真实的、最小的发光二极管(LED/OLED 像素点)。
- 特性: 出厂即固定。我们常说的屏幕分辨率(如
1170 x 2532、4K)指的就是物理像素的总数。 - 决定了: 屏幕的绝对清晰度上限。
逻辑像素 (Logical Pixel / CSS Pixel / DIP)
- 本质: 一个虚拟的、相对的单位。在 Web 开发中,它就是你写的
px;在移动端操作系统中,它被称为dp(Android) 或pt( iOS)。 - 特性: 由操作系统定义。它的存在是为了保证同一个 UI 元素在不同高低分辨率的屏幕上,**肉眼看到的物理尺寸(厘米/毫米)基本保持一致 **。
- 决定了: 程序员和设计师排版时的坐标系。
为什么会诞生 DPR
在 iPhone 4 (Retina 屏幕) 问世之前,DPR 统统都是 1。1 个 CSS 像素对应 1 个物理像素。
但随着屏幕技术发展,手机物理尺寸没变,但屏幕里塞进去了多一倍的物理发光点。
- 如果依然让 1 CSS像素 = 1 物理像素,那么以前画的一个宽
44px的按钮,在视网膜屏幕上看起来只有原来的一半大,人类的手指根本点不到。 - 操作系统的解决方案: 引入 DPR。系统强行规定,在 Retina 屏幕上,逻辑坐标系依然不变(比如屏幕宽度还是当作 320),但底层渲染时,用
2x2 = 4个物理像素去画这 1 个逻辑像素。这就保证了按钮“物理大小不变”,但“清晰度翻倍”。
浏览器是如何“知道” DPR 的
这是一个从硬件到软件的信息传递链:
- 硬件层: 屏幕面板出厂时,固化了物理分辨率和物理尺寸信息。
- 系统层: 操作系统(如 iOS/Android)读取硬件信息,为了保证人眼阅读的舒适度,计算并设定了一个默认的“逻辑分辨率”,并得出了当前的缩放比(DPR)。
- 应用层(浏览器/Webview): 浏览器向操作系统查询当前的窗口/视口信息,拿到了 DPR 的值。
- 生效关键: 开发者必须在 HTML 的
<head>中写入包含<meta name="viewport" content="width=device-width">的标签,告诉浏览器严格按照操作系统的逻辑宽度去排版,DPR 机制才算真正生效。
如何在代码中获取和使用 DPR
JavaScript 获取
可以直接通过 window 对象获取当前运行环境的 DPR,这在写 Canvas 绘图代码时非常重要:
js
const dpr = window.devicePixelRatio;CSS 媒体查询匹配
可以利用媒体查询,针对不同 DPR 的屏幕应用不同的样式(常用于加载不同精度的背景图):
css
/* 针对 DPR >= 2 的高清屏幕 */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
.bg-icon {
background-image: url('icon@2x.png');
}
}
/* 针对 DPR >= 3 的超清屏幕 */
@media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 3dppx) {
.bg-icon {
background-image: url('icon@3x.png');
}
}🤔 “1px 变粗”问题
在 DPR=2 的屏幕上写 border: 1px,浏览器会用 2 排物理像素去画。在极其细腻的文字和图片对比下,这条线显得比设计师预期(真正的 1 个物理发光点宽度)要粗重笨拙。
- 使用 CSS 伪元素结合
transform: scale(0.5)。强行将元素尺寸缩小一半,逼迫浏览器只用 1 排物理像素渲染。
🤔 高清屏下的“图片模糊”问题
一张 200x200(物理像素)的普通图片(JPG/PNG),放在宽高设置了 200px(逻辑像素)的 <img> 标签里。在 DPR=2 的屏幕上,浏览器为了填满这块逻辑区域,会强行分配 400x400 的物理发光点去渲染。像素不够,只能强行拉伸插值,导致边缘发虚、模糊。
- 准备多套分辨率的图片(如
@2x.png,@3x.png),并配合 HTML5 的srcset或<picture>标签,让浏览器根据当前设备的 DPR 自动下载对应的高清图。
@keyboarder-yang