设备像素比(dpr)使1px变粗是因浏览器将1个CSS逻辑像素按dpr倍数(如dpr=2时铺满2个物理像素)直接拉伸渲染,无降采样和亚像素优化,导致边框发虚偏粗;0.5px兼容差、不可靠;最稳解法是::after+transform:scaleY(0.5),需配position:relative、transform-origin:0 100%、height:1px+background-color及pointer-events:none。

移动端写 border: 1px 看起来像 2px 或更粗,不是 CSS 写错了,是设备像素比(window.devicePixelRatio)在底层直接映射导致的——浏览器把 1 个 CSS 像素拉伸成多个物理像素渲染,且不降采样、不抗锯齿优化边框。
devicePixelRatio 是怎么让 1px 变粗的
iPhone 8 的 dpr = 2,iPhone 13 是 dpr = 3,安卓中常见 dpr = 2 或 dpr = 3。这时:
- 你写的 border-width: 1px 是逻辑像素单位;
- 浏览器按 dpr 倍数把它铺满对应数量的物理像素(比如 2×2 或 3×3 区域);
- 没有亚像素对齐机制,也没有边缘锐化,结果就是一条发虚、偏粗、带灰边的线。
这不是 bug,是所有现代移动浏览器的标准行为。
为什么 border-width: 0.5px 几乎不能用
0.5px 听起来最直觉,但落地极难:
- iOS Safari 直到 13+ 才开始有限支持,iOS 12 及更早版本直接忽略;
- 安卓 WebView(尤其 Android 4.4–6.0 系统自带)普遍四舍五入为 1px 或当 0px 渲染;
- 即使生效,getComputedStyle(el).borderWidth 仍返回 "1px",调试时完全不可靠;
- 0.5px 无法和 border-radius 共存,圆角会截断边框;
- 颜色无法继承,必须每个地方硬写 border-color,也不支持 CSS 变量动态控制。
::after + transform: scaleY(0.5) 为什么最稳
这个方案绕开了浏览器对非整数 border-width 的限制,用视觉缩放模拟物理像素精度:
- 伪元素画一个 height: 1px 的 background-color 条,再用 transform: scaleY(0.5) 压它;
- 关键约束必须齐备:父元素设 position: relative,伪元素加 transform-origin: 0 100%(下边框)或 0 0(四边),并始终配 pointer-events: none;
- 不依赖 dpr 检测,不改 viewport,不影响字体/间距/布局流;
- iOS 12–15 需补 -webkit-transform 和 -webkit-transform-origin 前缀;
- content 必须是非空字符串(哪怕只是 ''),background-color 必须显式声明,不能靠继承。
四边 1px 边框最容易漏掉的盒模型细节
单边用 scaleY 或 scaleX 很简单,但四边一起上,稍不注意就错位、溢出、被裁:
- 伪元素必须设 top: 0; left: 0; right: 0; bottom: 0;,再配合 width: 200%; height: 200% + transform: scale(0.5);
- 必须写 box-sizing: border-box,否则默认 content-box 会让边框外扩,缩放后四角露白或黑线;
- transform-origin 改为 0 0(左上角),避免内容变化导致锚点偏移;
- 若父容器有 overflow: hidden,缩放后的伪元素可能被裁——因为缩放基于原始 200% 尺寸计算,坐标系未同步收缩,此时应改用 clip-path: inset(0) 替代。
真正容易被忽略的,是伪元素的 content 和 background-color ——它们既不继承、也不能省略,而且圆角场景下该方案会失真,得换 linear-gradient 或 border-image。


















