为什么会有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:
通常手机端的页面设计稿都是放大一倍的,如:为适应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:
样式设置:
.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;