# 疑难杂症
# 1 移动端物理像素问题
设备像素比就是设备的物理像素与逻辑像素的比值,公式表达如下:dpr = window.devicePixelRatio。retina 屏的手机, dpr 值等于 2 或 3,什么意思呢?就是 css 样式里写的 1px 映射到物理像素上就有 2px 或 3px。
那么如何实现移动端的 1px
# 伪类 + transform + 媒体查询
不使用原来 border 设置边框,改用其伪类来模拟 border,通过媒体查询和 transform 的 scale 大小来改变边框值。
.border-1px {
position: relative;
box-sizing: border-box;
width: 100%;
padding: 10px;
text-align: center;
}
.border-1px:after {
position: absolute;
top: 0;
left: 0;
content: '';
box-sizing: border-box;
border: 1px solid red;
border-radius: 10px;
transform-origin: 0 0;
}
@media (-webkit-min-device-pixel-ratio: 2) {
.border-1px::after {
width: 200%;
height: 200%;
transform: scale(0.5);
}
}
@media (-webkit-min-device-pixel-ratio: 3) {
.border-1px::after {
width: 300%;
height: 300%;
transform: scale(0.333);
}
}
- 优点是所有场景都能满足
- 缺点是兼容性
# 小数方案 + 媒体查询
通过媒体查询,给不同 dpr
设置不同单位边框值。
.border-1px {
text-align: center;
padding: 10px;
border-radius: 5px;
border: 1px solid red;
}
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.border-1px {
border: 0.5px solid red;
}
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
.border-1px {
border: 0.333px solid red;
}
}
- IOS8+ 苹果系列都已经支持单位小数方案了
- IOS7及以下和 Android,小数方案会显示为 0px,可以通过
window.devicePixelRatio
来写 Hack - 优点就是简单,代码少
- 缺点就是兼容性差
# viewport + rem
通过 javascript 更改 viewport 的 rem 基准值,这样就可以继续写 px 了。
- 比如 dpr = 2 时,
<meta name="viewport" content="width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
- 比如 dpr = 3 时,
<meta name="viewport" content="width=device-width,initial-scale=0.333, maximum-scale=0.333, minimum-scale=0.333, user-scalable=no">
.border-1px {
box-sizing: border-box;
padding: 1rem;
text-align: center;
border: 1px solid red;
border-radius: 0.5rem;
}
const viewport = document.querySelector('meta[name=viewport]');
const dpr = window.devicePixelRatio || 1;
const scale = (1 / dpr).toFixed(3);
viewport.setAttribute('content', 'width=device-width,' + 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
const docEl = document.documentElement;
const fontsize = 10 * (docEl.clientWidth / 320) + "px";
docEl.style.fontSize = fontsize;
- 优点就是只适用于新项目,一套代码兼容所有布局
- 缺点就是老项目修改代价大
# 图片方式
不管通过 border-image
还是 background-image
,修改边框颜色需要换图片,圆角还需单独处理且边缘模糊。
# 插件 postcss-write-svg
项目中使用 PostCSS
,然后安装这个插件。
@svg border-1px-base {
height: 2px;
@rect {
fill: var(--color, gray);
width: 100%;
height: 50%;
}
}
.border-1px {
border: 1px solid transparent;
border-image: svg(border-1px param(--color red)) 2 2 stretch;
}