为什么会有1px的问题

首先有一个dpr的概念,dpr也就是设备像素比: dpr = window.devicePixelRatio = 物理像素/逻辑像素。

出现移动端1px问题主要是因为设备的物理像素和逻辑像素不同导致的,不同的设备所拥有的物理像素是不同的,也称硬件像素,在pc上一般dpr=1,但是在移动设备中dpr常常不为1,这也就导致了在移动端上1px展示的看起来比较粗。

解决方案
1、媒体查询和0.5px
@media screen and (-webkit-min-device-pixel-ratio: 2) {
	div {
		border-width: 0.5px;
	}
}
/*ios dpr=2和dpr=3情况下border相差无几,下面代码可以省略*/
@media screen and (-webkit-min-device-pixel-ratio: 3) {
	div {
		border-width: 0.333333px;
	}
}

缺点:这种方式部分浏览器会不支持0.5px,会把0.5px解释为0px,这个时候我们就可以通过js来检测浏览器能否处理0.5px的边框

if (window.devicePixelRatio && devicePixelRatio >= 2) {
  	var testElem = document.createElement('div');
  	testElem.style.border = '.5px solid transparent';
  	document.body.appendChild(testElem);
}
if (testElem.offsetHeight == 1) {
  	document.querySelector('html').classList.add('hairlines');
}
  	document.body.removeChild(testElem);
}
div {
  	border: 1px solid #bbb;
}
.hairlines div {
  	border-width: 0.5px;  
}
2、使用border-image实现

首先准备一张符合你要求的border-image:

1px没有转rem_圆角


通常手机端的页面设计稿都是放大一倍的,如:为适应iphone retina,设计稿会设计成750*1334的分辨率,图片按照2倍大小切出来,在手机端看着就不会虚化,非常清晰。 同样,在使用border-image时,将border设计为物理1px,如下:

样式设置:

.border-image-1px {
    border-width: 0 0 1px 0;
    border-image: url(linenew.png) 0 0 2 0 stretch;
}

上文是把border设置在边框的底部,所以使用的图片是2px高,上部的1px颜色为透明,下部的1px使用视觉规定的border的颜色。如果边框底部和顶部同时需要border,可以使用下面的border-image:

1px没有转rem_scala_02


样式设置:

.border-image-1px {
    border-width: 1px 0;
    -webkit-border-image: url(linenew.png) 2 0 stretch;
    border-image: url(linenew.png) 2 0 stretch;
}

到目前为止,我们已经能在iPhone上展现1px border的效果了。但是我们发现这样的方法在非视网膜屏上会出现border显示不出来的现象,于是使用Media Query做了一些兼容,样式设置如下:

.border-image-1px {
    border-bottom: 1px solid #666;
} 
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
    .border-image-1px {
        border-bottom: none;
        border-width: 0 0 1px 0;
        -webkit-border-image: url(../img/linenew.png) 0 0 2 0 stretch;
        border-image: url(../img/linenew.png) 0 0 2 0 stretch;
    }
}

优点:可以设置单条,多条边框,没有性能瓶颈的问题
缺点:修改颜色麻烦, 需要替换图片;圆角需要特殊处理,并且边缘会模糊

3、使用background-image实现

background-image跟border-image的方法一样,你要先准备一张符合你要求的图片,然后将边框模拟在背景上。
样式设置:

.background-image-1px {
  background: url(../img/line.png) repeat-x left bottom;
  -webkit-background-size: 100% 1px;
  background-size: 100% 1px;
}

优点:可以设置单条,多条边框,没有性能瓶颈的问题。
缺点:修改颜色麻烦, 需要替换图片;圆角需要特殊处理,并且边缘会模糊。

4、使用多背景渐变实现

与background-image方案类似,只是将图片替换为css3渐变。设置1px的渐变背景, 50%有颜色,50%透明。样式设置:

.background-gradient-1px{
	background:
	linear-gradient(180deg, black, black 50%, transparent 50%) top 1eft / 100% 1px no-repeat,
	linear-gradient(90deg, b1ack, black 50%, transparent 50%) top right / 1px 100% no-repeat,
	linear-gradient(0, black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat,
	1inear-gradient(-90deg, black, black 50%, transparent 50%) bottom 1eft / 1px 100% no-repeat;
}
/*或者*/
. background-gradient-1px{
	background: -webkit-gradient(linear, 1eft top, 1eft bottom, color-stop(.5, transparent),
	color-stop(.5, #c8c7cc), to(#c8c7cc)) 1eft bottom repeat-x;
	background-size: 100% 1px;
}

缺点:因为每个边框都是线性渐变颜色实现,因此无法实现圆角。

5、使用box-shadow模拟边框实现

样式设置:

div {
    -webkit-box-shadow: 0 1px 1px -1px #c8c7cc;
}

优点是没有圆角问题,缺点是颜色不好控制

6、使用transform加伪类实现(较常用)

样式设置:

div::after{
    content:'';width:100%;
    border-bottom:1px solid #000;
    transform: scaleY(0.5);
}
/* 2倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
    .border-bottom::after {
        -webkit-transform: scaleY(0.5);
        transform: scaleY(0.5);
    }
}
/* 3倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
    .border-bottom::after {
        -webkit-transform: scaleY(0.33);
        transform: scaleY(0.33);
    }
}
7、使用viewport+rem实现(较常用)

通过js监听dpr,设置meta标签相应的属性

<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
var viewport = document.querySelector("meta[name=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.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
} 
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;