移动端 1px 边框

Monday, April 1st 2019, 7:10:26 am ( ISO 8601 )

标签:

布局方面,css有那么几个比较热衷的问题。其中,移动端1px边框问题的讨论不亚于垂直居中。 那么移动端1px边框问题是如何产生的呢?由于现在的手机几乎都是retina屏,css设置的1px会被渲染成2px的物理像素(针对像素比等于2的屏幕),因此看起来会比较粗。 既然知道了问题的产生原因,那么我们就开始解决。网上有很多种方案,但实际上我们用的时候只能选一种用,所以那么“不靠谱”的就不详细叙述了…(以下方案推荐指数逐渐提高)

1. 直接设置0.5px

ios8+可以识别浮点类型的单位,因此可以渲染这个0.5px。然而,绝大部分的android机是不支持浮点类型单位的。所以这种方案pass…

2. 利用背景图

不管是border-image,还是background-image,图片的弊端还是很明显的:想改变颜色就必须要换图片,而且利用图片也比较麻烦。所以不推荐这种方案…

3. 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页面的终端适配》

4. 背景渐变实现

与background-image方案类似,只是将图片替换为css3渐变。设置1px的渐变背景,50%有颜色,50%透明。很多UI都是采用这种方法,比如:weui、mint-ui… 单边:

.background-gradient-1px {
    background-image: linear-gradient(180deg, #f8f8f8, #f8f8f8 50%, transparent 50%);
    background-size: 100% 1px;
    background-repeat: no-repeat;
    background-position: bottom left;
    background-origin: content-box;
}

四边:(多背景渐变)

.background-gradient-1px {
    background:
        linear-gradient(#000, #000 100%, transparent 100%) left / 1px 100% no-repeat,
        linear-gradient(#000, #000 100%, transparent 100%) right / 1px 100% no-repeat,
        linear-gradient(#000,#000 100%, transparent 100%) top / 100% 1px no-repeat,
        linear-gradient(#000,#000 100%, transparent 100%) bottom / 100% 1px no-repeat
}
/* 或者 */
.background-gradient-1px {
    background:
        -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) left / 1px 100% no-repeat,
        -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) right / 1px 100% no-repeat,
        -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) top / 100% 1px no-repeat,
        -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) bottom / 100% 1px no-repeat
}

这种方案显示是比较牛*的,不仅实现了1px的边框,还能实现多条边框。缺点就是不能实现圆角的1px边框,浏览器的兼容性也要考虑…

5. 伪类 + transform 实现

个人认为伪类 + transform 是比较完美的方法。利用 :before 或者 :after 实现 border,并 transform 的 scale 缩小一半,将 border 绝对定位。 单边:

.scale-1px {
    position: relative;
    border: none;
}
.scale-1px:after{
    content: '';
    position: absolute;
    bottom: 0;
    width: 100%;
    height: 1px;
   background: #000;
    -webkit-transform: scaleY(0.5);
    transform: scaleY(0.5);
    -webkit-transform-origin: 0 0;
    transform-origin: 0 0;
}

@media (-webkit-min-device-pixel-ratio:3),(min-device-aspect-ratio:3){
    .scale-1px:after {
        -webkit-transform:scaleY(0.333);
        transform:scaleY(0.333);
    }
}

四边:

.scale-1px {
    position: relative;
    margin-bottom: 20px;
    border: none;
}
.scale-1px:after{
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid #000;
  -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;
}
/* 或者: */
.scale-1px:after{
    content: '';
    position: absolute;
    border: 1px solid #000;
    top: -50%;
    right: -50%;
    bottom: -50%;
    left: -50%;
     -webkit-transform: scale(0.5);
    transform: scale(0.5);
}

至此,移动端1px的实现就这么多,如有更牛*的方案,欢迎补充~

原文地址


Toweave

关于作者
本人是前端工程师 Toweave. 一个努力成为优秀工程师的男人.了解更多...

文章精选.

程序员的文字障
Friday, May 28th 2021, 2:31:26 am ( ISO 8601 )
什么是文字障?
文件类型判断
Friday, April 12th 2019, 1:51:30 am ( ISO 8601 )
常用的文件类型判断
vue 实例生命周期钩子
Thursday, April 11th 2019, 9:15:48 am ( ISO 8601 )
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。
浏览器运行环境判断
Thursday, April 11th 2019, 9:05:35 am ( ISO 8601 )
常用的浏览器运行环境判断
现在很多人开网约车,这样能赚多少钱,能够赚到大钱吗?
苏州-虎丘
Saturday, April 6th 2019, 3:05:22 am ( ISO 8601 )
苏州虎丘一日游。
日积月累,你将完成不可思议的事情。
Wednesday, April 3rd 2019, 8:08:38 am ( ISO 8601 )
日积月累,你将完成不可思议的事情。
JavaScript Date 对象
Wednesday, April 3rd 2019, 6:18:56 am ( ISO 8601 )
Date 对象用于处理日期和时间。
常用正则表达式
Wednesday, April 3rd 2019, 3:47:31 am ( ISO 8601 )
正则表达式,一个十分古老而又强大的文本处理工具,仅仅用一段非常简短的表达式语句,便能够快速实现一个非常复杂的业务逻辑。熟练地掌握正则表达式的话,能够使你的开发效率得到极大的提升。下面是在前端开发中经常使用到的20个正则表达式。
上海-一朵梨花压海棠
Wednesday, April 3rd 2019, 3:05:22 am ( ISO 8601 )
一朵梨花压海棠。
CSS Selector 选择器
Tuesday, April 2nd 2019, 10:15:53 am ( ISO 8601 )
了解并且熟用 CSS3 为我们提供的强大并且优雅的选择器,就可以简化我们的代码。
对前端工程师的误解
Tuesday, April 2nd 2019, 9:51:16 am ( ISO 8601 )
隔行如隔山,经常会有一些不太了解前端工作者对前端开发的误解。
Material Design 中文版
Tuesday, April 2nd 2019, 9:28:52 am ( ISO 8601 )
Material Design 的核心思想,就是把物理世界的体验带进屏幕。去掉现实中的杂质和随机性,保留其最原始纯净的形态、空间关系、变化与过渡,配合虚拟世界的灵活特性,还原最贴近真实的体验,达到简洁与直观的效果。
Markdown - 使用指南
Tuesday, April 2nd 2019, 8:50:09 am ( ISO 8601 )
是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用。
浮点数运算的精度问题
Monday, April 1st 2019, 10:33:53 am ( ISO 8601 )
根据浮点数的定义,非整数的 Number 类型无法用 `==` 来比较(`===` 也不行)
上海-顾村公园
Saturday, March 23rd 2019, 3:05:22 am ( ISO 8601 )
上海-顾村公园,摄影。
上海-世纪公园
Sunday, March 17th 2019, 3:05:22 am ( ISO 8601 )
上海-世纪公园,摄影。
Toweave's logo.
Sunday, March 3rd 2019, 8:08:38 am ( ISO 8601 )
Toweave's logo. 哈哈,2015 年,为自己设计的 logo。