Grid子项间隙在Retina屏下显示为1px虚线或露白,是因非整数逻辑像素触发亚像素插值;需确保尺寸为整数、用translateZ(0)触发合成层、以伪元素替代gap实现物理像素对齐。

Grid子项间隙在Retina屏下显示为1px虚线或露白
这不是gap值写错了,而是浏览器对非整数逻辑像素做亚像素插值的结果。当grid-template-columns用1fr 1fr等比例划分,且容器宽度为奇数(如375px),每个子项算出来是187.5px——这个0.5px在DPR=2设备上会触发sub-pixel渲染,交界处就出现半透明缝隙或发虚边框。
用DevTools勾选“Show Rasterization Borders”能看到交界处有浅灰色描边;调用el.getBoundingClientRect().left返回小数也佐证了这一点。
- 确保父容器宽度为偶数:用
width: calc(100% - 1px)或媒体查询强制修正,比如@media (min-width: 375px) { .grid { width: 374px; } } - 避免
1fr在奇数宽容器中参与计算:改用repeat(2, minmax(0, 1fr)))或显式指定整数列宽(如200px 200px) - 给子项加
transform: translateZ(0)触发合成层,让浏览器以device pixel为单位重绘边界
使用gap属性时DPR=2/3下实际物理像素超标
gap: 1px在DPR=2设备上会被渲染为2物理像素宽,视觉上比设计稿粗一倍。这不是bug,是CSS像素映射规则决定的——你写的1px是逻辑像素,不是物理像素。
直接写gap: 0.5px不可靠:Android WebView普遍忽略,iOS Safari 12及更早版本直接退回到0px,只有Safari 13+部分支持。
立即学习“前端免费学习笔记(深入)”;
- 用伪元素替代
gap:给每个子项右/下边加::after,设height: 1px+background,再配合scaleY(0.5)缩放 - 父容器必须设
position: relative,否则伪元素定位脱标 -
transform-origin必须写全,如下边距用0 100%,不能只写bottom(Safari解析不稳定) - 务必加
pointer-events: none,否则安卓WebView可能拦截点击
Grid + Flex混合布局中baseline错位放大缝隙
当Grid子项内嵌Flex容器,且含文字或图片时,vertical-align: baseline(默认行为)会让子项底部对齐基准线偏移,DPR高时这种偏移被放大成可见缝隙。
检查是否用了align-items: stretch但子项内部有未重置的line-height或font-size——这些非整数值会进一步加剧亚像素误差。
- Grid子项统一设
align-items: flex-start或align-items: start,避开baseline计算 - 子项内文字相关属性(
font-size、line-height、height)全部用整数,禁用rem或em动态单位 - 父容器加
text-size-adjust: none防iOS系统字体缩放干扰
为什么display: grid加overflow: hidden没用
overflow: hidden只能裁剪溢出内容,不能抑制sub-pixel插值。缝隙本质是两个相邻渲染单元在亚像素边界上的颜色混合,不是布局溢出问题。
同理,border-collapse、backface-visibility: hidden或强行加margin: -0.5px都治标不治本——前者无效,后者在DPR=3设备上会错位更严重。
真正起效的是控制输入值(尺寸、字号、gap)为整数 + 触发独立合成层(translateZ(0)) + 用伪元素绕过浏览器border解析链。这三者缺一不可。


















