如何在移动端实现1像素细线
在高分辨率设备下,1px就等于96分之一英寸,约等于0.2646mm
在移动端中,宽度100%,1px的线看起来要比pc端中宽100%,1px的线粗,那是因为css中的1px并不等于移动设备(物理像素)的1px。物理像素显示是1个像素代表2个像素,所以出现为2px
所以我们在移动端中为了让1px的线“看起来”苗条些,会采用一些手段。
使用box-shadow模拟边框
利用css 对阴影处理的方式实现1px的效果
样式设置:
.box-shadow-1px {
box-shadow: inset 0px -1px 1px -1px #c8c7cc;
}
取值说明:<inset offsetx offsety blur spread color>
inset: 默认阴影在边框外。使用 inset 后,阴影在边框内(即使是透明边框),背景之上内容之下。也有些人喜欢把这个值放在最后,浏览器也支持。
<offset-x> <offset-y>: 这是头两个 <length>值,用来设置阴影偏移量。<offset-x> 设置水平偏移量,如果是负值则阴影位于元素左边。 <offset-y> 设置垂直偏移量,如果是负值则阴影位于元素上面。可用单位请查看 <length>。如果两者都是0,那么阴影位于元素后面。这时如果设置了 <blur-radius> 或 <spread-radius> 则有模糊效果。
<blur>: 这是第三个 <length> 值。值越大,模糊面积越大,阴影就越大越淡。 不能为负值。默认为0,此时阴影边缘锐利。
<spread> : 这是第四个 <length> 值。取正值时,阴影扩大;取负值时,阴影收缩。默认为0,此时阴影与元素同样大。
<color> : 相关事项查看 <color>。如果没有指定,则由浏览器决定——通常是color的值,不过目前Safari取透明。
优点:
代码量少,可以满足所有场景
缺点:
边框有阴影,颜色变浅
viewport + rem 实现
同时通过设置对应viewport的rem基准值,这种方式就可以像以前一样轻松愉快的写1px了。
在devicePixelRatio = 2 时,输出viewport:
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
在devicePixelRatio = 3 时,输出viewport:
<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">
这种兼容方案相对比较完美,适合新的项目,老的项目修改成本过大。
对于这种方案,可以看看《使用Flexible实现手淘H5页面的终端适配》
优点:
所有场景都能满足,一套代码,可以兼容基本所有布局
缺点:
老项目修改代价过大,只适用于新项目
JS + border
解决方案是通过 JavaScript 检测浏览器能否处理0.5px的边框,如果可以,给html标签元素添加个class。
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() {})
然后,极细的边框样式就容易了:
div {
border: 1px solid #bbb;
}
.hairlines div {
border-width: 0.5px;
}
优点:
简单,不需要过多代码。
缺点:
无法兼容安卓设备、 iOS 8 以下设备。
background-image && boder-image
典型的跳过设置1px这个问题的解决方法
.background-image-1px {
background: url(...) no-repeat left bottom;
-webkit-background-size: 100% 1px;
background-size: 100% 1px;
}
.border-bottom-1px {
border-width: 0 0 1px 0;
-webkit-border-image: url(...) 0 0 2 0 stretch;
border-image: url(...) 0 0 2 0 stretch;
}
优势: 至少解决了问题
劣势: 我想换个颜色还得换图,而且图片处理圆角会出现模糊的问题
伪元素 + scale缩放
话说前头,大力推荐。直接上代码。ant-design-mobile同样使用这种处理
@border-color-base : #EBEDF0;
// 伪元素的位置控制
.scale-hairline-common(@color, @top, @right, @bottom, @left) {
content: '';
position: absolute;
background-color: @color;
display: block;
z-index: 1;
top: @top;
right: @right;
bottom: @bottom;
left: @left;
}
//上边框
.hairline(@direction, @color: @border-color-base) when (@direction ='top') {
border-top: 1PX solid @color;
@media (min-resolution: 2dppx) {
border-top: none;
&::before {
.scale-hairline-common(@color, 0, auto, auto, 0);
width: 100%;
height: 1PX;
transform-origin: 50% 50%;
transform: scaleY(0.5);
@media (min-resolution: 3dppx) {
transform: scaleY(0.33);
}
}
}
}
// 右边框
.hairline(@direction, @color: @border-color-base) when (@direction ='right') {
border-right: 1PX solid @color;
@media (min-resolution: 2dppx) {
border-right: none;
&::after {
.scale-hairline-common(@color, 0, 0, auto, auto);
width: 1PX;
height: 100%;
background: @color;
transform-origin: 100% 50%;
transform: scaleX(0.5);
@media (min-resolution: 3dppx) {
transform: scaleX(0.33);
}
}
}
}
// 下边框
.hairline(@direction, @color: @border-color-base) when (@direction ='bottom') {
border-bottom: 1PX solid @color;
@media (min-resolution: 2dppx) {
border-bottom: none;
&::after {
.scale-hairline-common(@color, auto, auto, 0, 0);
width: 100%;
height: 1PX;
transform-origin: 50% 100%;
transform: scaleY(0.5);
@media (min-resolution: 3dppx) {
transform: scaleY(0.33);
}
}
}
}
// 左边框
.hairline(@direction, @color: @border-color-base) when (@direction ='left') {
border-left: 1PX solid @color;
@media (min-resolution: 2dppx) {
border-left: none;
&::before {
.scale-hairline-common(@color, 0, auto, auto, 0);
width: 1PX;
height: 100%;
transform-origin: 100% 50%;
transform: scaleX(0.5);
@media (min-resolution: 3dppx) {
transform: scaleX(0.33);
}
}
}
}
// 全边框
.hairline(@direction, @color: @border-color-base, @radius: 0) when (@direction ='all') {
border: 1PX solid @color;
border-radius: @radius;
@media (min-resolution: 2dppx) {
position: relative;
border: none;
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 200%;
height: 200%;
border: 1PX solid @color;
border-radius: @radius * 2;
transform-origin: 0 0;
transform: scale(0.5);
box-sizing: border-box;
pointer-events: none;
}
}
}
具体使用:
.div1{
.hairline('top',#eeeeee)
.hairline('right')
.hairline('left',#cccccc)
}
.div2{
.hairline('all',#bbbbbb,3px)
}
优势:
使用less将css接口化,功能灵活,复用性和兼容性较好,通过媒体查询适配了2倍屏和3倍屏。该代码写在公共css样式中即可。
劣势:
代码仍然有继续抽象的空间,并且此方案是使用positon:absolute进行定位,所以父元素也必须满足绝对定位的触发条件。
#前端高频面试##面试##面筋##你觉得今年春招回暖了吗##23届找工作求助阵地#