多倍屏上实现小于 1px 的边框/直线

高倍屏中小于 1px 的边框/直线,例如,某手机为三倍屏,CSS 中写 1px,对应设备像素为 3px。而我们希望实现的效果为 CSS 中的 2/3px,即设备像素 2px。

而通常浏览器会采取「四舍五入」或「下取整」等方式进行解析,因此,无法直接在 CSS 中使用小数作为属性值。

添加伪元素样式

可以使用伪元素 + transform 解决这一问题。

基本原理是将边框设置为 1px,宽高设为目标元素的 n 倍,再等比缩小 n 倍。

举例说明「边框」实现方法 (SCSS):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 边框缩放倍数 */
$borderScale: 0.5;
$borderScaleTimes: 1/$borderScale;

.box-border {
position: relative;

&:before {
content: "";
position: absolute;
top: 0;
left: 0;
bottom: (1-$borderScaleTimes)*100%;
right: (1-$borderScaleTimes)*100%;
border: 1px solid #e6e6e6;
transform: scale($borderScale);
transform-origin: 0 0;
box-sizing: border-box;
}
}

其中,$borderScale 为缩放倍数,例如: $borderScale: 0.667 将 1px 的边框缩小到 0.667px,实际显示为 2/3px 设备像素。

类似地,也可以实现多倍屏中小于 1px 直线。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* 直线缩放倍数 */
$lineScale: 0.667;

.box-line {
position: relative;

// 水平直线,默认底边
&:after {
content: "";
width: 100%;
height: 1px;
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: #ebebeb;
transform: scaleY($lineScale);
transform-origin: 0 100%;
}

// 垂直直线,默认右边
&.line-vertical:after {
width: 1px;
height: 100%;
top: 0;
left: auto;
right: 0;
bottom: 0;
transform: scaleX($lineScale);
transform-origin: 100% 0;
}
}

使用

实际应用时,根据设计要求设置不同的 $borderScale/$lineScale 的值,并在需要设置边框的元素上添加名为 box-border/box-line 的 class 即可。例如:

/* 边框缩放倍数 */    
$borderScale: 0.667;  
$lineScale: 0.5;
<div class="square box-border">边框</div>
<div class="square box-line">底边</div>
<div class="square box-line line-vertical">右边</div>