您是否注意到 1px 边框在移动设备上有时会显得比预期的要粗?这种不一致源于移动屏幕的像素密度不同。
在 Web 开发中,我们使用 CSS 来设置页面样式。但是,CSS 中的 1px 并不总是转换为设备上的物理 1px。这种差异就是我们的“1px 边框问题”产生的原因。
罪魁祸首:像素密度
每个设备都拥有特定的像素密度,由 devicePixelRatio 测量,它告诉我们物理像素与设备独立像素之间的比率。
devicePixe
lRatio = 物理像素 / 独立
像素
今天我就来跟你分享8 个久经考验的解决方案 。
探索解决方案,我们要重点关注像素比大于或等于 2 的情况。
1. 0.5px 边框:一个简单的解决方案
此方法涉及在设备像素比为 2 或更高时有条件地应用 0.5px 边框。
if(window.devicePixelRatio && devicePixelRatio>=2){
var testElem = document.createElement('div');
testElem.style.border = '.5px solid transparent';
document.body.appendChild(testElem);
if(testElem.offsetHeight == 1){
document.querySelector('html').classList.add('hairlines');
}
document.body.removeChild(testElem);
}
div{
border: 1px solid #bbb;
}
.hairlines div {
border-width: 0.5px;
}
2. 边框图像:完美的边框
使用专门制作的边框图像是一种有效的方法。以下是创建底部边框的方法:
.border-bottom-1px {
border-width: 0 0 1px 0;
border-image: url(linenew.png) 0 0 2 0 stretch;
-webkit-border-image: url(linenew.png) 0
0 2 0 stretch;
}
解释:
-
我们只在底部设置边框(border-width:0 0 1px 0)。
-
使用的图像(“linenew.png”)假定为 2px 高。
-
图像顶部 1px 是透明的,底部 1px 包含实际边框颜色。
与 border-image 类似,此方法利用预先准备的图像作为边框。
.backround-image-1px{
background: url(../img/line.png) repeat-x left bottom;
-webkit-background-size: 100% 1px;
background-size: 100% 1px;
}
注意事项:
我们可以使用渐变背景来模仿边框的外观。渐变的一半显示所需的颜色,而另一半保持透明。
.background-gradient-1px{
background:
line-gradient(180deg, black, black 50%, transparent 50%) top left / 100% 1px no-repeat,
line-gradient(90deg, black, black 50%, transparent 50%) top right / 1px 100% no-repeat,
line-gradient(0, black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat,
line-gradient(-90deg, black, black 50%, transparent 50%) bottom left / 1px 100% no-repeat;
}
.background-gradient-1px{
background: -webkit-gradient(linear, left top, left bottom,
color-step(.5, transparent),
color-step(.5, #c8c7cc),
to(#c8c7cc))
left bottom repeat-x;
background-size: 100% 1px;
}
5. Box-Shadow:跳出框框
让我们利用 CSS 阴影来创建令人信服的边框效果。
.box-shadow-1px {
box-shadow: inset 0px -1px 1px -1px #c8c7cc;
}
6. 视口 + Rem:动态二重奏
调整视口的 rem 基值有助于在不同设备上实现一致的 1px 边框。请记住,使用此技术修改旧项目可能需要进行重大调整。
优点:
适用于各种布局的适应性解决方案。
缺点:
对于遗留项目来说可能具有挑战性。
// For a device pixel ratio of 1, set the viewport as follows:
name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
// For a device pixel ratio of 2
name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
// For a device pixel ratio of 3
name="viewport" content="initial-scale=0.333333, maximum-scale=0.333333, minimum-scale=0.333333, user-scalable=no">
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport"
content="width=device-width,initial-scale=1,user-scalable=no"
/>
<title>rem+viewporttitle>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#box {
width: 8rem;
height: 8rem;
border: 1px solid #000;
}
style>
head>
<body>
<div id="box">div>
<script type="text/javascript">
var dpr = window.devicePixelRatio;
console.log(dpr, 'dpr+++');
var scale = 1 / dpr;
var width = document.documentElement.clientWidth;
var metaNode = document.querySelector('meta[name="viewport"]');
metaNode.setAttribute('content', 'width=device-width,initial-scale=' + scale + ',user-scalable=no');
var width = document.documentElement.clientWidth;
var styleN = document.createElement('style');
styleN.innerHTML = 'html{font-size: ' + width / 16 + 'px !important;}';
document.head.appendChild(styleN);
script>
body>
html>
7. 伪元素 + 变换:传统项目英雄
这种方法对现有项目非常方便。我们删除原始边框,并利用伪元素制作 1px 边框,将其缩小以获得像素完美的外观。
.scale-1px {
position: relative;
border: none; // Remove any default borders
}
.scale-1px:after {
content: '';
position: absolute;
bottom: 0;
background: #000; // Set the desired border color
width: 100%;
height: 1px;
transform: scale(0.5); // Scale down to 0.5 to achieve a thinner border
transform-origin: 0 0;
}
.scale-1px-top {
border: none;
position: relative;
}
.scale-1px-top:before {
content: '';
position: absolute;
display: block;
top: 0;
left: 0;
width