如何在移动端实现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届找工作求助阵地#
全部评论

相关推荐

威猛的小饼干正在背八股:挂到根本不想整理
点赞 评论 收藏
分享
与火:这不接? 留子的钱不挣白不挣
点赞 评论 收藏
分享
评论
3
6
分享
牛客网
牛客企业服务