关于解决移动端Retina屏幕1px边框问题的方法

造成边框变粗的原因

在 CSS 中的 1px 并不等于移动设备的 1px。这是由于不同的手机有不同的像素密度,在浏览器的 window 对象中有一个 devicePixelRatio 属性,可以反应 CSS 中像素与设备的像素比。

devicePixelRatio 的官方定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素

解决边框变粗的六种方法

0.5px 边框

在 2014 年的 WWDC,“设计响应的 web 体验”一讲中,Ted O’Connor 讲到关于“retinahairlines”的处理方法:

通过 JavaScript 检测浏览器能否处理 0.5px 的边框,如果可以,给 HTML 标签元素添加一个类。

1
2
3
4
5
6
7
div{
border: 1px solid #bbb;
}

.hairlinds div{
border-width: 0.5px;
}
1
2
3
4
5
6
7
8
9
if(window.devicePixelRatio && devicePixelRatio >= 2){
var testElem = document.createElement('div');
testElem.style.border = '0.5px solid transparent';
document.body.appendChild(testElem);
if(testElem.offsetHeight == 1){
document.querySelector('html').classList.add('hairlines');
}
document.body.removeChild(testElem);
}

使用 border-image 或者 background-image

使用一张 2px 的图片,根据需求留空 1px,剩余 1px 为边框颜色。

1
2
3
4
5
6
div {
-moz-border-image: url(/i/border.png) 30 30 stretch; /* Old Firefox */
-webkit-border-image: url(border.png) 30 30 stretch; /* Safari 5 */
-o-border-image: url(border.png) 30 30 stretch; /* Opera */
border-image: url(border.png) 30 30 stretch;
}
1
2
3
4
5
.background-image-1px {
background: url(../img/line.png) repeat-x left bottom;
-webkit-background-size: 100% 1px;
background-size: 100% 1px;
}

缺点:

  1. 修改颜色麻烦,需要替换图片
  2. 圆角需要特殊处理,某些设备上边缘会模糊

使用 box-shadow 模拟边框

1
2
3
.box-shadow-1px {
box-shadow: inset 0px -1px 1px -1px #ddd;
}

优点:代码少,兼容性好。

缺点:边框有阴影,颜色变浅。

伪元素+transform

构建 1 个伪元素, border 为 1px, 再以 transform 缩放到 50%。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 设计稿是750,采用1:100的比例,font-size为100*(100vw/750) */
.border-1px {
position: relative;
}
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.border-1px:before {
content: ' ';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
border-top: 1px solid #ddd;
color: #ddd;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}

优点:可以满足所有场景,兼容好,且修改灵活。
缺点:对于已使用伪类的元素要多层嵌套。

用 JS 计算 rem 基准值和 viewport 缩放值

用 JS 根据屏幕尺寸和 dpr 精确地设置不同屏幕所应有的 rem 基准值和 initial-scale 缩放值,这个 JS 方案已经在完美解决了 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
/* 设计稿是750,采用1:100的比例,font-size为100 * (docEl.clientWidth * dpr / 750) */

var dpr, rem, scale;
var docEl = document.documentElement;
var fontEl = document.createElement('style');
var metaEl = document.querySelector('meta[name="viewport"]');
dpr = window.devicePixelRatio || 1;
rem = 100 * ((docEl.clientWidth * dpr) / 750);
scale = 1 / dpr;
// 设置viewport,进行缩放,达到高清效果
metaEl.setAttribute(
'content',
'width=' +
dpr * docEl.clientWidth +
',initial-scale=' +
scale +
',maximum-scale=' +
scale +
', minimum-scale=' +
scale +
',user-scalable=no'
);
// 设置data-dpr属性,留作的css hack之用,解决图片模糊问题和1px细线问题
docEl.setAttribute('data-dpr', dpr);
// 动态写入样式
docEl.firstElementChild.appendChild(fontEl);
fontEl.innerHTML = 'html{font-size:' + rem + 'px!important;}';

参考:https://www.cnblogs.com/superlizhao/p/8729190.html