物理像素 vs 逻辑像素:交互式指南(附你屏幕的真实数据)
你的屏幕——实时检测:
你把显示器设为 3840×2160,但 JavaScript 里 screen.width 说的是 2560(screen.height 是 1440)。你截个图——3840 像素宽。你在 CSS 里写 width: 100px,实际渲染出来是 200 个物理像素。怎么回事?
你的屏幕实际上在跑两套分辨率系统——物理像素(硬件上真实的发光点)和逻辑像素(软件用来布局的单位)。两者之间的比例就是设备像素比(DPR),它影响着屏幕上的每一个坐标。你屏幕的真实数据已经显示在上方。
打开免费屏幕坐标工具你的屏幕数据——实时检测
在讲理论之前,先看看你屏幕现在的实际参数:
这些数值来自浏览器真实的 API,不是猜测。"估算"的物理分辨率是通过 screen.width × DPR 和 screen.height × DPR 算出来的,大多数情况下跟真实硬件一致,但可能受 GPU 虚拟超分辨率或浏览器缩放影响。如果 DPR 是 1.0,你的物理像素和逻辑像素完全一致。如果更高,说明软件看到的和屏幕实际显示之间存在一层转换。用我们的屏幕坐标工具可以实时查看这对鼠标位置的影响。
什么是物理像素?
物理像素(也叫设备像素)是屏幕硬件上一个真实的发光点。它是显示器上最小的可寻址单元。在 LCD 面板上,每个物理像素由三个子像素(红、绿、蓝)组成,它们共同产生一个颜色的点。
显示器的物理分辨率告诉你它到底有多少个这样的点:
- 1920×1080 显示器有 2,073,600 个物理像素
- 3840×2160(4K)显示器有 8,294,400 个物理像素
- iPhone 15 Pro 在 6.1 英寸的屏幕上有 2,556×1,179 个物理像素
物理像素对一块给定的显示器来说是固定的。4K 显示器始终有 3840×2160 个物理像素,不管你的 Windows 缩放设置怎么改。硬件是写死的。
关于不同物理像素数量对坐标系的影响,参见我们的屏幕分辨率对比指南。
什么是逻辑像素(CSS 像素)?
逻辑像素(也叫CSS 像素、设备独立像素(DIP),或 macOS 上的点(point))是软件用来布局的计量单位。它是一个抽象概念——一个逻辑像素不一定等于一个物理像素。
在标准的 1080p 显示器上开 100% 缩放,一个逻辑像素 = 一个物理像素,很简单。但在 DPR 为 2 的 Retina MacBook Pro 上,一个逻辑像素 = 2×2 的物理像素网格(共 4 个物理像素)。在 Windows 4K 显示器开 150% 缩放上,一个逻辑像素 = 1.5×1.5 的物理像素区域。
为什么需要逻辑像素:没有它的话,一个设为 100×30 像素的按钮在 4K 手机屏幕上(像素微乎其微)会小到看不见,在 720p 投影仪上又大得离谱。逻辑像素让开发者写 width: 100px 就能在所有设备上呈现差不多的物理大小,不用操心像素密度。
直观对比——每个彩色方块代表一个物理像素。一个逻辑像素在不同的 DPR 下对应不同的网格:
DPR 1(1 CSS 像素 = 1×1)
DPR 1.5(1 CSS 像素 = 1.5×1.5)
DPR 2(1 CSS 像素 = 2×2)
DPR 3(1 CSS 像素 = 3×3)
设备像素比:物理与逻辑之间的桥梁
设备像素比(DPR)是逻辑像素和物理像素之间的转换系数:
物理像素 = 逻辑像素 × DPR
示例(仅宽度):
1920 逻辑 × DPR 1.0 = 1920 物理 (标准 1080p)
2560 逻辑 × DPR 1.5 = 3840 物理 (4K 开 150% 缩放)
1440 逻辑 × DPR 2.0 = 2880 物理 (MacBook Retina)
在 JavaScript 中,你可以通过 window.devicePixelRatio 读取 DPR。这个值是只读的——由你的显示器硬件和操作系统缩放设置决定。
DPR 不一定是整数
Windows 常用的是小数 DPR 值:1.25(125%)、1.5(150%)、1.75(175%)。macOS 在 Retina 显示器上固定使用 2.0。Android 设备的值五花八门(1.5、2.0、2.625、3.0、3.5、4.0)。小数 DPR 意味着逻辑像素不能整齐地映射到物理像素——一个逻辑像素可能覆盖多个物理像素的一部分,这就是为什么 Windows 在 125% 缩放下文字渲染看起来会有点模糊。
关于 DPR 如何在 Windows 上与 DPI 缩放交互并搞坏自动化脚本,参见我们的DPI 缩放与坐标指南。
各设备的 DPR:MacBook、Windows、Android、iPhone
常见设备及其 DPR 值:
| 设备 | 物理分辨率 | 逻辑分辨率 | DPR | 1 个 CSS 像素 = |
|---|---|---|---|---|
| 标准 PC 显示器(1080p) | 1920×1080 | 1920×1080 | 1.0 | 1 个物理像素 |
| Windows 4K 开 150% | 3840×2160 | 2560×1440 | 1.5 | 2.25 个物理像素 |
| Windows 4K 开 200% | 3840×2160 | 1920×1080 | 2.0 | 4 个物理像素 |
| MacBook Pro 14" | 3024×1964 | 1512×982 | 2.0 | 4 个物理像素 |
| MacBook Pro 16" | 3456×2234 | 1728×1117 | 2.0 | 4 个物理像素 |
| iPad Pro 11" | 2388×1668 | 1194×834 | 2.0 | 4 个物理像素 |
| iPhone 15 Pro | 2556×1179 | 393×852 | 3.0 | 9 个物理像素 |
| Pixel 8 | 2400×1080 | 412×915 | ~2.625 | ~6.9 个物理像素 |
| Samsung Galaxy S24 | 2340×1080 | 360×780 | ~3.0 | 9 个物理像素 |
规律很明显:Apple 坚持整数 DPR(2 或 3)。Windows 用小数值(1.25、1.5、1.75)来实现更精细的缩放控制。现代应用和浏览器通过子像素渲染能很好地处理小数 DPR——只有老旧的、不支持 DPI 感知的应用才会被位图拉伸而变模糊。Android 的值因厂商而异。
这对屏幕坐标和自动化意味着什么
那么实际有什么影响?
- 自动化工具对坐标的理解不一致。没有 DPI 感知的 PyAutoGUI 使用逻辑坐标,而 Windows API
GetCursorPos(对 DPI 感知进程)返回物理坐标。混着用就全偏了,偏移量就是 DPR 的倍数。我们的PyAutoGUI 坐标指南有修复方法。 - 截图捕获的是物理像素。4K 显示器开 150% 缩放时,一张截图是 3840×2160——不是 2560×1440。想用逻辑坐标在截图里定位 UI 元素?先乘以 DPR。
- CSS 坐标永远是逻辑的。设
left: 100px; top: 200px,那些都是逻辑像素——浏览器在后台帮你转成物理像素。所以getBoundingClientRect()返回的是 CSS 像素。 - 多显示器环境可能有混合 DPR。Retina 笔记本屏幕(DPR 2)旁边接一台标准外接显示器(DPR 1),同一个坐标在两块屏幕上映射到不同的物理位置。我们的多显示器坐标指南专门讲了这种情况。
速查表:你用的是哪种坐标系?
| 工具 / API | 坐标类型 | 报告的分辨率 |
|---|---|---|
| PyAutoGUI(默认) | 逻辑 | 逻辑(如 2560×1440) |
| PyAutoGUI(加 SetProcessDPIAware) | 物理 | 物理(如 3840×2160) |
| AutoHotkey A_ScreenWidth | 逻辑 | 逻辑 |
| Windows GetCursorPos(DPI 感知) | 物理 | 物理 |
| JavaScript screen.width/height | 逻辑(CSS) | 逻辑 |
| JavaScript window.innerWidth | 逻辑(CSS) | 逻辑 |
| CSS getBoundingClientRect() | 逻辑(CSS) | 不适用 |
| macOS NSScreen(Quartz) | 点(逻辑) | 点 |
常见问题
DPR 和 DPI 是一回事吗?
有关系但不一样。DPI(每英寸点数)衡量的是物理像素密度——一英寸的屏幕里塞了多少像素。DPR(设备像素比)是物理像素和逻辑像素的比率。一块高 DPI 屏幕如果操作系统不缩放,DPR 可能还是 1。DPR 讲的是软件映射关系,DPI 讲的是硬件密度。
为什么 Retina Mac 看起来比 4K Windows PC 更清晰?
macOS 用的是整数 DPR(2.0),意味着每个 CSS 像素精确对应一个 2×2 的物理像素网格——干净的 4:1 映射。Windows 常用小数 DPR(1.25、1.5、1.75),一个 CSS 像素对应的是非整数个物理像素。这会导致子像素渲染伪影,不支持 DPI 感知的应用会出现轻微模糊。
能改 DPR 吗?
可以间接通过操作系统的缩放设置来改。Windows:设置 → 系统 → 显示 → 缩放与布局。macOS:系统设置 → 显示器 → 选择"默认"使用原生 DPR,或选择"缩放"使用不同的逻辑分辨率。Android:设置 → 显示 → 显示大小 / 字体大小(控制有限)。DPR 会立即改变,但有些应用需要重启才能生效。
为什么 window.devicePixelRatio 在不同显示器上会变?
如果你把浏览器从 DPR 1.0 的外接显示器拖到 DPR 2.0 的 Retina 笔记本屏幕上,window.devicePixelRatio 会自动更新为新显示器的 DPR。你可以通过 matchMedia('(resolution: ' + dpr + 'dppx)') 的 change 事件来监听。需要处理混合 DPI 环境的 Web 应用应该关注这一点。