好记性不如烂笔头〜
我决定要把 「移动端1px细线解决方案」
做个笔记,跟大家分享一下。
移动端1px变粗的原因
移动端css里面写了1px,实际比1px粗。
其实原因很好理解:这两个'px'的含义是不一样的。
移动端的 <header>
头里有这样一段代码:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
代码解析:
-
name="viewport" content="width=device-width
:本页面的 “ viewport” 的宽度为设备宽度。 -
initial-scale=1.0, maximum-scale=1.0
:初始缩放值和最大的缩放值都为1。 -
user-scalable=no
:禁止用户进行页面缩放。
移动端 window
对象有个 devicePixelRatio
属性,为设备投入比。
「drp = window.devicePixelRatio,也就是设备的物理指示与逻辑指示的比值。」
「以iPhone6应该:」
它的物理推测是750,逻辑推测为375,所以iphone6的drp = 2。
所以css里面写的1px宽度映射到物理预定上就有2px。
解决方案
一,使用小数来写px值
在ios8 +中当drp = 2的时候使用0.5px,使用媒体查询
.border { border: 1px solid #999 }
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.border { border: 0.5px solid #999 }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
.border { border: 0.333333px solid #999 }
}
二,使用box-shadow模拟边框
利用css对阴影处理的方式实现0.5px的效果
样式设置:
.box-shadow-1px {
box-shadow: inset 0px -1px 1px -1px #c8c7cc;
}
三,:之前,:之后与转换
构建1个伪元素,将其的长宽放大到2倍,边框宽度设置为1px,再用transform缩放到50%。
我这里只写了上下边框,还有左右边框,你们可以模仿一下。
//所有边框
.mx-1px {
position: relative
}
.mx-1px:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 0;
top: 0;
left: 0;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
box-sizing: border-box
}
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.mx-1px:before {
width: 200%;
height: 200%;
-webkit-transform: scale(.5);
transform: scale(.5)
}
}
//上边框
.mx-1px-top {
position: relative
}
.mx-1px-top:before {
position: absolute;
content: "";
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
width: 100%;
height: 1px;
border-top: 1px solid #ccc;
top: 0;
left: 0
}
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.mx-1px-top:before {
-webkit-transform: scaleY(.5);
transform: scaleY(.5)
}
}
//下边框
.mx-1px-bottom {
position: relative
}
.mx-1px-bottom:before {
position: absolute;
content: "";
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
width: 100%;
height: 1px;
bottom: -1px;
border-bottom: 1px solid #ccc;
left: 0
}
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.mx-1px-bottom:before {
-webkit-transform: scaleY(.5);
transform: scaleY(.5)
}
}
四,视口+ rem + js
通过设置对应viewport
的scale
,这种方式就可以像以前一样轻松愉快的写1px了。
-
当drp = 1时:
initial-scale=1
-
当drp = 2时:
initial-scale=0.5
-
当drp = 3时:
initial-scale=0.3333333333333333
示例:
<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;
}
.top_b {
border-bottom: 1px solid #E5E5E5;
}
.a,.b {
box-sizing: border-box;
margin-top: 1rem;
padding: 1rem;
font-size: 1.4rem;
}
.a {
width: 100%;
}
.b {
background: #f5f5f5;
width: 100%;
}
</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 = 32* (docEl.clientWidth / 750) + 'px';
docEl.style.fontSize = fontsize;
</script>
</head>
<body>
<div class="top_b a">下面的底边宽度是虚拟1像素的</div>
<div class="b">上面的边框宽度是虚拟1像素的</div>
</body>
</html>
总结
对于老项目:采用伪类+ transform。
对于新项目:采用viewport的sacle值,这个方法兼容性好。