原因分析
网上流传着的错误说法: 原因是由于⾼分辨率屏幕的像素密度⽐传统的屏幕要⾼,所以在屏幕上显示的⼀个 CSS 像素对应的物理像素个数也会相应地增多,当使⽤ CSS 中的 1px 来设置边框或者细线时,实际上渲染出来的线条在屏幕上会被拆分为多个物理像素,从⽽导致看上去更粗。
但是不管 dpr 是多少,也就是不管 1px 对应的物理像素是多少,他始终都是 1px 的逻辑像素,这是由操作系统(浏览器)决定的,浏览器会自动处理 CSS 像素和物理像素之间的比例关系,确保网页元素在视觉上的大小保持一致。
正确说法: UI 给我们的移动端设计稿往往都是 750px 的,我们在实际设置时需要将这些尺寸设置为一半。而当他给我们 1px 的时候,我们只需要设置为 0.5px ,但是一些旧的设备或者浏览器默认最小只识别 1px ,这时可能设备 显示的是 0px。
常见解决方案
-
使⽤ viewport,在 head 中添加如下代码可以解决 1px 问题(viewport+rem+div:淘宝):
<meta name="viewport" content="width=device-width,initial scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
-
使⽤ scale + transform 缩放边框,以达到渲染 1 像素的效果。(伪元素 + transform :京东)例如:
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .text { display: inline-block; margin: 30px; /*border: 1px solid red;*/ /*如果直接给text设置transform: scale(0.5); 则这里面的所有元素都会缩小*/ /*transform: scale(0.5);*/ position: relative; } .text::after { content: ''; position: absolute; left: 0; top: 0; width: 200%; height: 200%; border: 1px solid red; /*transform: scale(0.5);会将宽高边框等都缩小0.5 所以宽高需要先扩大一倍*/ transform: scale(0.5); /*从左上角开始缩放 而不是元素的中心*/ transform-origin: 0 0; } </style> </head> <body> <!--添加0.5px 的边框--> <div class="text">满300减30</div> </body> </html>
-
使⽤图⽚代替边框或细线,这种⽅法能够保证显示效果的⼀致性,但是需要制作多张图⽚,增加了⻚⾯加载的开销。
-
使⽤ border-image,border-image 可以实现将⼀张图⽚作为边框样式,图⽚会⾃动拉伸或者重复以填充边框。这种⽅法需要制作⼀张边框的图⽚,但是可以通过 CSS 控制图⽚的填充⽅式和边框样式,⽐较灵活。例如:
.border { border: 1px solid transparent; border-image: url(border.png) 1 1 stretch; }
-
使⽤ CSS3 的 box-shadow,可以⽤ box-shadow 属性来模拟边框。例如:
.border { box-shadow: 0 0 0 1px #000; }
-
使用 rem 。按照比例呈现 1px 。
-
背景图 background-image 。
.line { width: 100%; height: 1px; background-image: linear-gradient(to right, black 50%, transparent 50%); background-size: 2px 1px; }
-
svg 线条:直接在 HTML 中放入一个 SVG 标签,设置线条的 strokeWidth 为 0.5。
<svg width="100%" height="1"> <line x1="0" y1="0" x2="100%" y2="0" style="stroke:black;stroke-width:0.5" /> </svg>