问题描述:移动端iPhone上的1px边框看起来像2px那么粗。
问题分析:不同的手机有不同的像素密度,在window对象中有一个devicePixelRatio属性,它可以反应设备的像素与css中的像素比。即devicePixelRatio=物理像素/独立像素。iPhone使用的是Retine屏,“Retina”是一种显示技术,可以把更多的像素点压缩至一块屏幕里,从而达到更高的分辨率并提高屏幕显示的细腻程度。因为Retine屏的分辨率始终是普通屏幕的2倍,1px的边框在devicePixelRatio=2的Retine屏下会显示成2px,所以css设置1px的样式,实际是2px的效果。
解决方案:
1、用小数实现
div { border: 1px solid #dfdfdf; } @media screen and (-webkit-min-device-pixel-ratio: 2) { div { border: 0.5px solid #dfdfdf; } } @media screen and (-webkit-min-device-pixel-ratio: 3) { div { border: 0.333333px solid #dfdfdf; } }
无法兼容安卓设备和iOS8以下的设备。
2、用border-image实现
.border-image-1px { border-bottom: 1px solid #dfdfdf; } @media 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/dot.png) 0 0 2 0 stretch; border-image: url(../img/dot.png) 0 0 2 0 stretch; } }
修改颜色麻烦,需要替换图片,圆角需要特殊处理。
3、用background-image实现
@media screen and (-webkit-min-device-pixel-ratio: 2) { .background-image-1px { background: url(../img/line.png) repeat-x left bottom; -webkit-background-size: 100% 1px; background-size: 100% 1px; } }
修改颜色麻烦,需要替换图片,圆角需要特殊处理。
4、用多背景渐变实现
@media screen and (-webkit-min-device-pixel-ratio: 2) { .background-gradient-1px { background: linear-gradient(#dfdfdf, #dfdfdf 100%, transparent 100%) left / 1px 100% no-repeat, linear-gradient(#dfdfdf, #dfdfdf 100%, transparent 100%) right / 1px 100% no-repeat, linear-gradient(#dfdfdf,#dfdfdf 100%, transparent 100%) top / 100% 1px no-repeat, linear-gradient(#dfdfdf,#dfdfdf 100%, transparent 100%) bottom / 100% 1px no-repeat } }
/* 或者 */
@media screen and (-webkit-min-device-pixel-ratio: 2) { .background-gradient-1px{ background: -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #dfdfdf), to(#dfdfdf)) left / 1px 100% no-repeat, -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #dfdfdf), to(#dfdfdf)) right / 1px 100% no-repeat, -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #dfdfdf), to(#dfdfdf)) top / 100% 1px no-repeat, -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #dfdfdf), to(#dfdfdf)) bottom / 100% 1px no-repeat } }
圆角没法实现,多背景图片有兼容性问题。
5、用box-shadow实现
.box-shadow-1px { box-shadow: inset 0px -1px 1px -1px #dfdfdf; }
边框有阴影,颜色变浅。
6、用viewport+rem实现
devicePixelRatio=2时,
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
devicePixelRatio=3时,
<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">
这种兼容方案相对比较完美,适合新的项目,老的项目修改成本过大。
手淘H5页面就采用了Flexible技术,核心是viewport+rem。
7、用伪元素+transform实现
原理是,把元素的border去掉,然后利用:before或者:after重做border,并让transform的 scale缩小一半,元素本身相对定位,新做的border绝对定位。
@media only screen and (-webkit-min-device-pixel-ratio: 2.0){ .border-1px, .border-top-1px, .border-right-1px ,.border-bottom-1px , .border-left-1px{ position: relative; border:none; } /*线条颜色*/ .border-1px:after, .border-top-1px:after, .border-right-1px:after, .border-bottom-1px:after, .border-left-1px:after { background-color: #f00; } /*上边边框一像素*/ .border-top-1px:after { pointer-events: none; content:""; position: absolute; left:; top:; width: 100%; height: 1px; transform-origin: 0 0; transform: scaleY(0.5); } /*右边边框一像素*/ .border-right-1px:after { pointer-events: none; content:""; position: absolute; right:; bottom:; width: 1px; height: 100%; transform-origin: 0 0; transform: scaleX(0.5); } /*底边边框一像素*/ .border-bottom-1px:after { pointer-events: none; content:""; position: absolute; left:; bottom:; width: 100%; height: 1px; transform-origin: 0 0; transform: scaleY(0.5); } /*左边边框一像素*/ .border-left-1px:after { pointer-events: none; content:""; position: absolute; left:; top:; width: 1px; height: 100%; transform-origin: 0 0; transform: scaleX(0.5); } /*边框一像素*/ .border-1px:after { pointer-events: none; content: ""; box-sizing: border-box; position: absolute; left:; top:; width: 200%; height: 200%; border: 1px solid #dfdfdf; -webkit-transform: scale(0.5); transform: scale(0.5); -webkit-transform-origin: left top; transform-origin: left top; } }
@media only screen and (-webkit-min-device-pixel-ratio: 3.0){ .border-1px, .border-top-1px, .border-right-1px ,.border-bottom-1px , .border-left-1px{ position: relative; border:none; } /*线条颜色*/ .border-1px:after, .border-top-1px:after, .border-right-1px:after, .border-bottom-1px:after, .border-left-1px:after { background-color: #f00; } /*上边边框一像素*/ .border-top-1px:after { pointer-events: none; content:""; position: absolute; left:; top:; width: 100%; height: 1px; transform-origin: 0 0; transform: scaleY(0.333); } /*右边边框一像素*/ .border-right-1px:after { pointer-events: none; content:""; position: absolute; right:; bottom:; width: 1px; height: 100%; transform-origin: 0 0; transform: scaleX(0.333); } /*底边边框一像素*/ .border-bottom-1px:after { pointer-events: none; content:""; position: absolute; left:; bottom:; width: 100%; height: 1px; transform-origin: 0 0; transform: scaleY(0.333); } /*左边边框一像素*/ .border-left-1px:after { pointer-events: none; content:""; position: absolute; left:; top:; width: 1px; height: 100%; transform-origin: 0 0; transform: scaleX(0.333); } /*边框一像素*/ .border-1px:after { pointer-events: none; content: ""; box-sizing: border-box; position: absolute; left:; top:; width: 300%; height: 300%; border: 1px solid #dfdfdf; -webkit-transform: scale(0.333); transform: scale(0.333); -webkit-transform-origin: left top; transform-origin: left top; } }