跳到主要内容

解决移动端 1px 的问题

· 阅读需 3 分钟

问题

一些移动设备的高分辨率屏幕(如 Retina 屏)具有较高的设备像素比(Device Pixel Ratio, DPR),例如 DPR=23。此时,CSS 中的 1px 会被渲染为 23 个物理像素,导致视觉上线条变粗。

方案一:伪元素 + transform 缩放

具体方法:结合伪元素(::after)通过 transform: scaleY(0.5); 缩放将实际边框的宽度减半,需保证父级元素相对布局 position: relative

.border-1px {
position: relative;
}
.border-1px::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px; /* CSS 像素 */
background-color: #e0e0e0;
transform: scaleY(0.5); /* Y 轴缩放为 50% */
transform-origin: 0 0; /* 从底部开始缩放 */
}

/* 适配不同DPR的媒体查询 */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
.border-1px::after {
transform: scaleY(0.5);
}
}
@media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 3dppx) {
.border-1px::after {
transform: scaleY(0.333);
}
}

方案二:使用 meta + viewport 动态缩放

具体方法:通过 JavaScript 动态设置 <meta>标签的 initial-scale,使 CSS 像素与物理像素对齐,需结合 REM 布局使用,确保整体布局适应缩放。

<meta
name="viewport"
id="viewportMeta"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>
<script>
const dpr = window.devicePixelRatio;
const scale = 1 / dpr;
const meta = document.getElementById('viewportMeta');
meta.content = `width=device-width, initial-scale=${scale}, maximum-scale=${scale}, user-scalable=0`;
// 调整根字体大小以保持布局比例(假设设计稿为 750px 宽)
document.documentElement.style.fontSize = 100 * (window.innerWidth / 750) * dpr + 'px';
</script>

方案三:使用图片 border-image 切图

具体方法:使用 border-image 图片替代边框,通过精确控制图片显示区域。

.border-image-1px {
border-width: 1px 0;
border-image: url(border.png) 2 0 stretch;
}
/* border.png 为高度 2px 的图片,上半透明,下半为实色 */

svg 矢量绘制

具体方法:利用 svg 的矢量特性实现高精度线条。

.svg-border {
background: url("data:image/svg+xml;utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%'><line x1='0' y1='100%' x2='100%' y2='100%' stroke='#e0e0e0' stroke-width='1'/></svg>");
}

方案对比

  • 推荐通用场景:优先使用 伪元素 + transform,结合媒体查询适配不同 DPR;
  • 新项目全局适配:采用 viewport 缩放 + rem 布局,需注意动态计算字体大小;
  • 复杂边框需求:使用 svg 方案,确保高清显示;
  • 兼容旧浏览器:备用 border-image 方案。