最优解是伪元素+transform:scaleY(0.5),需同时满足:父元素position:relative、伪元素height:1px+background-color、transform-origin:left bottom、pointer-events:none,缺一即失效。

移动端小数像素模糊不是“渲染不准”,而是浏览器在亚像素位置强行插值的结果——0.5px边框、transform: scale(0.75)拉伸、line-height: 1.25导致的行高错位,本质都是逻辑像素无法对齐物理栅格。
为什么0.5px边框在部分安卓机上根本画不出来
Android WebView 和旧版 Chrome 不支持 sub-pixel 渲染,border: 0.5px会被直接四舍五入成 1px 或丢弃;iOS Safari 虽能解析,但实际渲染仍依赖 DPR 对齐,DPR=1.5(如部分三星中端机)时,0.5px对应 0.75 物理像素,浏览器只能插值填充,必然发虚。
- 不要用
@media单独写border: 0.333px适配 DPR=3:浮点精度误差 + 浏览器截断 = 实际仍是1px - 避免
transform: scale(0.5)作用于带边框的容器:缩放会把 border 宽度也缩,但 border 的渲染逻辑独立于 transform,结果是边框被二次插值 - 检查是否启用了
-webkit-appearance: none:某些自定义input组件下,该属性会干扰原生边框渲染,让小数值失效
::after + transform: scaleY(0.5) 必须满足的四个硬性条件
这是目前兼容性最稳的伪元素方案,但漏掉任一条件就会偏移、断裂或遮挡交互:
-
position: relative必须加在父元素上,否则::after的bottom: 0无参照系 -
height: 1px不能换成border-bottom: 1px solid——后者缩放后仍走插值路径,模糊不减 -
transform-origin: left bottom必须与bottom: 0配合,否则scaleY(0.5)会从顶部向下压缩,压出半像素空隙 -
pointer-events: none缺失会导致伪元素覆盖点击区域,尤其在表单内易引发 focus 失效
background-image 用 image-set() 还是糊?先看三件事
image-set() 在移动端失效,90% 是因为没过基础校验:
立即学习“前端免费学习笔记(深入)”;
- 路径必须加引号且统一:三行声明中
"icon@2x.png"的引号类型(单/双)必须完全一致,否则 Safari 直接忽略整条规则 - 分辨率描述符必须带单位:
2x✅,2❌,2xpx❌;Firefox 完全不支持,安卓需用-webkit-image-set()前置 - 兜底顺序不能错:
background-image: url("icon@1x.png");必须放在最前,否则 Safari 16.4+ 可能跳过整个声明块
真正容易被忽略的模糊源:font-size 计算后低于 16px + line-height 过小
Android 系统级文本渲染会在 font-size < 16px 时降级为灰度模式,此时哪怕 CSS 写了 font-smoothing: antialiased 也无效;更隐蔽的是,line-height: 1 会让相邻文字基线挤压,笔画粘连感加剧模糊。
-
input和textarea必须单独加固:font-size: 16px !important,否则获焦时 WebView 可能重置字号 - 避免用
rem计算后出现15.8px这类值:Chrome 会向下取整,实际渲染为15px,触发模糊阈值 -
letter-spacing: 0.02em搭配font-size: 16px比单纯调大字号更有效——它拉开字符间距,减少视觉粘连


















