产生原因:
主要是跟一个东西有关,DPR(devicePixelRatio) 设备像素比,它是默认缩放为100%的情况下,设备像素和CSS像素的比值。
window.devicePixelRatio=物理像素 /CSS像素
非视网膜像素屏幕上,屏幕物理像素320像素,独立像素也是320像素,因此,window.devicePixelRatio等于1。
在视网膜屏幕的iphone上,屏幕物理像素640像素,独立像素还是320像素,因此,window.devicePixelRatio等于2.
目前主流的屏幕DPR=2 (iPhone 8),或者3 (iPhone 8 Plus)。拿2倍屏来说,设备的物理像素要实现1像素,而DPR=2,所以css 像素只能是 0.5。一般设计稿是按照750来设计的,它上面的1px是以750来参照的,而我们写css样式是以设备375为参照的,所以我们应该写的0.5px就好了啊! 试过了就知道,iOS 8+系统支持,安卓系统不支持。
场景:高分屏上会把1px宽的边框显示程2px,在dpr为3的设备上,显示边框为3px
解决方案:
- 边框的图片,border-image
.border-image-1px {
border-width: 1px 0px;
-webkit-border-image: url(border.png) 2 0 stretch;
border-image: url(border.png) 2 0 stretch;
}
- 背景图片
设置1px的渐变背景,50%有颜色,50%透明
.border {
background:
linear-gradient(180deg, black, black 50%, transparent 50%) top left / 100% 1px no-repeat,
linear-gradient(90deg, black, black 50%, transparent 50%) top right / 1px 100% no-repeat,
linear-gradient(0, black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat,
linear-gradient(-90deg, black, black 50%, transparent 50%) bottom left / 1px 100% no-repeat;
}
- 边框的阴影
.shadow {
-webkit-box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);
box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);
}
- 设置viewport的meta属性(不建议使用)
推荐方案:
1:transform:scale(0.5)
核心思想:使用transform的scale来整体缩放,把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。
单条border样式设置:
.scale-1px{
position: relative;
border:none;
}
.scale-1px:after{
content: '';
position: absolute;
bottom: 0;
background: #000;
width: 100%;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
四条border样式设置:
.scale-1px{
position: relative;
margin-bottom: 20px; border:none;
}
.scale-1px:after{
content: '';
position: absolute;
top: 0;
left: 0;
border: 1px solid #000;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 200%;
height: 200%;
-webkit-transform: scale(0.5);
transform: scale(0.5);
-webkit-transform-origin: left top;
transform-origin: left top;
}
结合js来代码来判断是否是Retina屏:
if(window.devicePixelRatio && devicePixelRatio >= 2){
document.querySelector('div').className = 'scale-1px';
}
2:viewport+rem实现
<span style="font-size:18px;"><html>
<head>
<title>1px question</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<style>
html {
font-size: 1px;
}
* {
padding: 0;
margin: 0;
}
.bds_b {
border-bottom: 1px solid #ccc;
}
.a,
.b {
margin-top: 1rem;
padding: 1rem;
font-size: 1.4rem;
}
.a {
width: 30rem;
}
.b {
background: #f5f5f5;
width: 20rem;
}
</style>
<script>
var viewport = document.querySelector("meta[name=viewport]");
//下面是根据设备像素设置viewport
if (window.devicePixelRatio == 1) {
viewport.setAttribute('content', 'width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no');
}
if (window.devicePixelRatio == 2) {
viewport.setAttribute('content', 'width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no');
}
if (window.devicePixelRatio == 3) {
viewport.setAttribute('content', 'width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');
}
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;
</script>
</head>
<body>
<div class="bds_b a">下面的底边宽度是虚拟1像素的</div>
<div class="b">上面的边框宽度是虚拟1像素的</div>
</body>
</html></span>