7 种方案解决移动端1px边框的问题
造成边框变粗的原因
css中的1px并不等于移动设备的1px,这是由不同手机由不同像素密度,在window对象中有一个devicePixelRatio属性,他可以反应css中像素与设备的像素比
devicePixelRatio 的官方给的定义为: 设备物理像素和设备独立像素的比例,也就是devicePixelRatio = 物理像素 / 独立像素。
解决边框变粗的6种办法
总结:
- 根据判断像素比大于等于2时,
1、0.5px边框
scss
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);
}
// 脚本放在内联,如果里面运行 需要包装$(document).ready(function(){})
css
div{
border: 1px solid #bbb
}
.hairlines div {
border-width: 0.5px;
}
2、使用border-image实现
准备一张符合要求的border-image
底部边框
css
.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设置在底部,图片2px高,上面1px颜色透明,下面1px使用规定的border颜色
3、使用background-image实现
和border-image实现类似,需要事先准备好图片
css
.backround-image-1px{
background: url(../img/line.png) repeat-x left bottom;
-wibkit-background-size:100% 1px;
background-size:100% 1px;
}
缺点:
- 修改颜色麻烦,需要替换图片
- 圆角需要特别处理,边缘会模糊
4、利用多背景渐变实现
与background-image类似,把图片改成渐变的背景,一半设置颜色,一半设置透明
scss
.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阴影的方式处理
css
.box-shadow-1px{
box-shadow: inset 0px -1px 1px -1px #c8c7cc
}
6、viewport + rem 实现
同时通过设置对应的viewport的rem基准值, 解决了1像素bug
这种方式比较完美,对老版本的修改不友好
优点:所有场景都能满足,一套代码,可以兼容所有布局
缺点:老项目修改代价过大
ini
// 在devicePixlRatio = 1 时, 输出viewport
<mate name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
// 在devicePixlRatio = 2 时, 输出viewport
<mate name="viewport" content="initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">
// 在devicePixlRatio = 3 时, 输出viewport
<mate name="viewport" content="initial-scale=0.333333,maximum-scale=0.333333,minimum-scale=0.333333,user-scalable=no">
xml
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,user-scalable=no"
/>
<title>rem+viewport适配</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#box {
width: 8rem;
height: 8rem;
border: 1px solid #000;
}
</style>
</head>
<body>
<div id="box"></div>
</body>
<script type="text/javascript">
//获取dpr
var dpr = window.devicePixelRatio; // 2
console.log(dpr, 'dpr+++');
//比例 // 0.5
var scale = 1 / dpr;
var width = document.documentElement.clientWidth; //375
//3.通过dpr让元素进行缩放,initial-scale=0.5
var metaNode = document.querySelector('meta[name="viewport"]');
metaNode.setAttribute(
'content',
'width=device-width,initial-scale=' + scale + ',user-scalable=no'
);
var width = document.documentElement.clientWidth; //750
//4.布局元素 单位 rem ,反向把缩放比例乘回来 2
var styleN = document.createElement('style');
styleN.innerHTML = 'html{font-size: ' + width / 16 + 'px !important;}';
document.head.appendChild(styleN);
</script>
</html>
7、使用伪类+transform实现
对于老项目,这种方案比较完美, 原理是把原来的所有边框去掉,通过伪类崇左border,并且transform的scale缩小一半,原先的单挑border样式设置
css
.scale-1px{
position:relative;
border:none;
}
.scale-1px:after{
content: '';
position:absolute;
bottom:0;
background: #000;
width:100%;
height:1px;
transform:scale(0.5);
transform-origin: 0 0;
}
.scale-1px-top {
/* border-bottom: 1px solid rgb(229, 229, 229); */
/* box-shadow: inset 0px -1px 1px -1px #c8c7cc; */
border:none;
position:relative;
}
.scale-1px-top:before{
content: '';
position: absolute;
display:block;
top: 0;
left: 0;
width: 200%;
height: 1px;
border-top: 1px solid #E7E7E7;
-webkit-transform: scale(0.5,0.5);
transform: scale(0.5,0.5);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
.scale-1px-bottom {
/* border-bottom: 1px solid rgb(229, 229, 229); */
/* box-shadow: inset 0px -1px 1px -1px #c8c7cc; */
border:none;
position:relative;
}
.scale-1px-bottom:before{
content: '';
position: absolute;
display:block;
bottom: -1px;
left: 0;
width: 200%;
height: 1px;
border-bottom: 1px solid #ccc;
-webkit-transform: scale(0.5,0.5);
transform: scale(0.5,0.5);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
.borderRadius-1px {
/* border-bottom: 1px solid rgb(229, 229, 229); */
/* 圆角(伪类和本体类都需要加border-radius) */
border-radius:.16rem;
border:none;
position:relative;
}
.borderRadius-1px:after{
/* 圆角(伪类和本体类都需要加border-radius) */
content: '';
position: absolute;
top: 0;
left: 0;
border: 1px solid #d1d1d1;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 200%;
height: 200%;
-webkit-transform: scale(0.5);
transform: scale(0.5);
-webkit-transform-origin: left top;
transform-origin: left top;
border-radius:.16rem;
}
8 、svg
css
<svg width=100% height=1 style="position: absolute;bottom: 0;left: 0;">
<line x1="0" y1="0" x2="1000" y2="0" style="stroke:#E5E5E5;stroke-width:1" />
</svg>