一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情
原因
css的1px在PC端就是1px; 在移动端就往往就大于 1pxcss的1px在PC端就是1px; 在移动端就往往就大于 1px
第一种方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>1px 问题</title>
<style>
body {margin:0;padding:19px}
div { padding:1em;margin:1em;}
.box1{border-top: 1px solid #000;}
.box2{border-bottom:1px solid #000;}
</style>
</head>
<body>
<div class="box1">
1px的上边框
</div>
<div class="box2">
0.5px的上边框
</div>
</body>
</html>
产生的原因
- 设备像素比:dpr=window.devicePixelRatio,也就是设备的物理像素与逻辑像素的比值。
- 在
retina
屏的手机上,dpr
为2
或3
,css
里写的1px
宽度映射到物理像素上就有2px
或3px
宽度。 - 例如:
iPhone6
的dpr
为2
,物理像素是750
(x轴),它的逻辑像素为375
。也就是说,1个逻辑像素,在x
轴和y
轴方向,需要2个物理像素来显示,即:dpr=2时,表示1个CSS像素由4个物理像素点组成。
解决方式
实现原理:伪元素 + transform 缩放
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>1px 问题</title>
<style>
body {margin:0;padding:19px}
div { padding:1em;margin:1em;}
.box1{border-top: 1px solid #000;}
.box2{position: relative;border-bottom:1px solid #000;}
.box2::after{
content:'';
position: absolute;
left:0;top:0;width: 100%;
height: 1px;
background-color: #000;
transform: scaleY(0.5);
}
</style>
</head>
<body>
<div class="box1">
1px的上边框
</div>
<div class="box2">
0.5px的上边框
</div>
</body>
</html>
伪元素
::after
或::before
独立于当前元素,可以单独对其缩放而不影响元素本身的缩放
优点:所有场景都能满足,支持圆角(伪类和本体类都需要加border-radius)。
缺点:代码量也很大,对于已经使用伪类的元素(例如clearfix),可能需要多层嵌套。
第二种方式
同时通过设置对应viewport
的rem
基准值,这种方式就可以像以前一样轻松愉快的写1px了。
在devicePixelRatio=2
时,设置meta
:
<meta name="viewport" content="width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
在devicePixelRatio=3
时,设置meta
:
<meta name="viewport" content="width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<title>移动端1px问题</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<meta name="viewport" id="WebViewport"content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<style>
html {
font-size: 11px;
}
body {
padding: 1rem;
}
* {
padding: 0;
margin: 0;
}
.item {
padding: 1rem;
border-bottom: 1px solid gray;
font-size: 1.2rem;
}
</style>
<script>
var viewport = document.querySelector("meta[name=viewport]");
var dpr = window.devicePixelRatio || 1;
var scale = 1 / dpr;
//下面是根据设备dpr设置viewport
viewport.setAttribute(
"content", +
"width=device-width," +
"initial-scale=" +
scale +
", maximum-scale=" +
scale +
", minimum-scale=" +
scale +
", user-scalable=no"
);
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + "px";
docEl.style.fontSize = fontsize;
</script>
</head>
<body>
<div class="item">border-bottom: 1px solid gray;</div>
<div class="item">border-bottom: 1px solid gray;</div>
</body>
</html>
优点:所有场景都能满足,一套代码,可以兼容基本所有布局。
缺点:老项目修改代价过大,只适用于新项目。