【本文目录】
- 前置概念
- 常见iPhone设备参数图
- 问题产生的根因
- 解决方案
- 总结
【前置概念】
屏幕尺寸:指的是屏幕对角线的长度
分辨率:是指宽度上和高度上最多能显示的物理像素点个数
点距:像素与像素之间的距离,点距和屏幕尺寸决定了分辨率大小
PPI:屏幕像素密度,即每英寸(1英寸=2.54厘米)聚集的像素点个数,这里的一英寸还是对角线长度
DPI:每英寸像素点,印刷行业术语。对于电脑屏幕而言和PPI是一个意思
设备像素(又称为物理像素): 指设备能控制显示的最小物理单位,意指显示器上一个个的点。从屏幕在工厂生产出的那天起,它上面设备像素点就固定不变了,和屏幕尺寸大小有关,单位 pt。
设备独立像素(也叫密度无关像素或逻辑像素):可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),这个点是没有固定下小的,越小越清晰,然后由相关系统转换为物理像素。
css像素(也叫虚拟像素):指的是 CSS 样式代码中使用的逻辑像素,在 CSS 规范中,长度单位可以分为两类,绝对(absolute)单位以及相对(relative)单位。px 是一个相对单位,相对的是设备像素(device pixel)
DPR(设备像素比):设备像素比 = 设备像素 / 设备独立像素。(在Retina屏的iphone上,DPR为2,1个css像素相当于2个物理像素)
【常见iPhone设备参数图】
【问题产生的根因】
在移动端开发的过程中这是必然要面临的一个问题。这个问题产生的原因就是*实际设备上2个或多个独立像素(可以简单理解为物理像素)*表示了1个逻辑像素(css中的px),导致了视觉上看到一的线条粗细和设计稿上的不符。
【解决方案】
- 利用伪元素::after + tranform 进行缩放(用伪元素的原因是因为伪元素是独立的元素,对齐缩放可以不影响目标元素)
- 利用媒体查询根据不同的DPR进行缩放
- 利用js 设置
init-scale
的值
利用伪元素::after + tranform 进行缩放
优点: 适合老项目,全机型兼容。
缺点:占用了伪元素
<div class="cell border-1px"> cell <div>
<style>
.cell {
width: 100px;
height: 100px;
}
<!--全部边框-->
.border-1px:after {
content: '';
position: absolute;
box-sizing: border-box;
top: 0;
left: 0;
width: 200%;
height: 200%;
border: 1px solid #000;
border-radius: 4px;
-webkit-transform: scale(0.5);
transform: scale(0.5);
-webkit-transform-origin: top left;
}
<!--单边框,以上边框为例-->
.border-1px-top:before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
border-top: 1px solid red;
transform: scaleY(.5);
transform-origin: left top;
}
</style>
利用媒体查询根据不同的DPR进行缩放
优点: 能实现。。。。
缺点: 麻烦且精确度不高
.border(
@borderWidth: 1px;
@borderStyle: solid;
@borderColor: @lignt-gray-color;
@borderRadius: 0) {
position: relative;
&:before {
content: '';
position: absolute;
width: 98%;
height: 98%;
top: 0;
left: 0;
transform-origin: left top;
-webkit-transform-origin: left top;
box-sizing: border-box;
pointer-events: none;
}
@media (-webkit-min-device-pixel-ratio: 2) {
&:before {
width: 200%;
height: 200%;
-webkit-transform: scale(.5);
}
}
@media (-webkit-min-device-pixel-ratio: 2.5) {
&:before {
width: 250%;
height: 250%;
-webkit-transform: scale(.4);
}
}
@media (-webkit-min-device-pixel-ratio: 2.75) {
&:before {
width: 275%;
height: 275%;
-webkit-transform: scale(1 / 2.75);
}
}
@media (-webkit-min-device-pixel-ratio: 3) {
&:before {
width: 300%;
height: 300%;
transform: scale(1 / 3);
-webkit-transform: scale(1 / 3);
}
}
.border-radius(@borderRadius);
&:before {
border-width: @borderWidth;
border-style: @borderStyle;
border-color: @borderColor;
}
}
.border-all(
@borderWidth: 1px;
@borderStyle: solid;
@borderColor: @lignt-gray-color;
@borderRadius: 0) {
.border(@borderWidth; @borderStyle; @borderColor; @borderRadius);
}
利用js 设置init-scale
的值
优点: 全机型兼容,方便
缺点: 不适合老项目
<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">
<script>
var viewport = document.querySelector("meta[name=viewport]");
//下面是根据设备像素设置viewport
viewport.setAttribute('content', `width=device-width,initial-scale=${1/window.devicePixelRatio}, maximum-scale=1, minimum-scale=1, user-scalable=no`);
</script>
</head>
</html>
总结:
新项目优先用:
js设置init-scale
的方式解决
老项目优先用:
利用伪元素::after + tranform 进行缩放的方式解决