微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

模拟 1px 的常用方法及利弊

2015-08-06 20:43 前端大全

(点击上方,可快速关注)


作者:百度EFE - wxpuker

网址:http://efe.baidu.com/blog/1px-on-retina/?qq-pf-to=pcqq.c2c

点击“阅读原文”可查看本文网页版


一直以来我们实现边框的方法都是设置 border: 1px solid #ccc,但是在retina屏上因为设备像素比的不同,边框在移动设备上的表现也不相同:1px可能会被渲染成1.5px, 2px, 2.5px, 3px....,在用户体验上略差,所以现在要解决的问题就是在retina屏幕实现1px边框。


如果你去google类似问题,诚然会找到所谓的”答案“,然后很开森的用到项目中了。运气好的话,Yeah成功模拟1px了,运气不好了可能遇到各种奇葩的表现让你抓狂。


这篇文章总结了目前常用的模拟1px的方法,并分析各个方法的利弊。


实现方案


1、软图片


‘软图片’,即通过CSS渐变模拟,代码如下:


.retina(@top: transparent, @right: transparent, @bottom: transparent, @left: transparent, @w: 1px) {

@media only screen and (-webkit-min-device-pixel-ratio: 2),

only screen and (min-device-pixel-ratio: 2) {

border: none;

background-image:

linear-gradient(180deg, @top, <a href='http://www.jobbole.com/members/ejiboth'>@top</a> 50%, transparent 50%),

linear-gradient(270deg, @right, @right 50%, transparent 50%),

linear-gradient(0deg, @bottom, @bottom 50%, transparent 50%),

linear-gradient(90deg, @left, @left 50%, transparent 50%);

background-size: 100% @w, <a href='http://www.jobbole.com/members/whch0919'>@w</a> 100%, 100% @w, <a href='http://www.jobbole.com/members/whch0919'>@w</a> 100%;

background-repeat: no-repeat;

background-position: top, right top, bottom, left top;

}

}


这段代码可能是从网上找到的出现最频繁的代码了,但是这样写是有兼容问题的,


测试小米2自带浏览器、手机百度、百度浏览器都显示不出上边框,如图:



测试小米2 chrome浏览器正常,如图:



这种情况我们会考虑是不是没有写浏览器前缀-webkit-的原因,好,我们加上:


background-image:

-webkit-linear-gradient(180deg, @top, <a href='http://www.jobbole.com/members/ejiboth'>@top</a> 50%, transparent 50%),

-webkit-linear-gradient(270deg, @right, @right 50%, transparent 50%),

-webkit-linear-gradient(0, @bottom, @bottom 50%, transparent 50%),

-webkit-linear-gradient(90deg, @left, @left 50%, transparent 50%);


再次检测小米2自带浏览器、手机百度、百度浏览器、chrome,这一次表现都一致!慢着好像有些不对:



怎么会这样呢??看样子是渐变方向不对,通过调整渐变方向得到结果:加上-webkit私有前缀的0deg的渐变方向是从左向右,而规范定义的0deg的渐变方向是自下而上。


知道原因了,我们再改改代码吧:


background-image:

-webkit-linear-gradient(270deg, @top, <a href='http://www.jobbole.com/members/ejiboth'>@top</a> 50%, transparent 50%),

-webkit-linear-gradient(180deg, @right, @right 50%, transparent 50%),

-webkit-linear-gradient(90deg, @bottom, @bottom 50%, transparent 50%),

-webkit-linear-gradient(0, @left, @left 50%, transparent 50%);

background-image:

linear-gradient(180deg, @top, <a href='http://www.jobbole.com/members/ejiboth'>@top</a> 50%, transparent 50%),

linear-gradient(270deg, @right, @right 50%, transparent 50%),

linear-gradient(0deg, @bottom, @bottom 50%, transparent 50%),

linear-gradient(90deg, @left, @left 50%, transparent 50%);


Done!


优点:


  • 可以实现单个、多个边框,大小、颜色可以配置

  • 对比下面介绍的其他方法,这个方法兼容性比较好,实现效果也相对不错


缺点:


  • 很明显代码特别长

  • 无法实现圆角

  • 使用时可能需要配合 padding,如设置子元素的背景可能会挡住父元素所设置的1px软图片

  • 如果有背景颜色,要写成background-color,不然会不小心覆盖掉

  • 对于非 retina 屏,需要写 border: 1px solid #f00 进行适配


2、缩放


‘缩放’,即使用css transform缩放一半的大小,代码如下:


.transform-scale {

position: relative;

&:after,

&:before {

content: '';

position: absolute;

left: 0;

top: 0;

height: 1px;

width: 100%;

-webkit-transform: scaleY(0.5);

transform: scaleY(0.5);

-webkit-transform-origin: 0 0;

transform-origin: 0 0;

background: #f00;

}

&:after {

top: auto;

bottom: 0;

-webkit-transform-origin: 0 100%;

transform-origin: 0 100%;

}

}


优点:


  • 实现单线条简单

  • 大小、颜色可以配置


缺点:


  • 无法实现圆角

  • 四条边框比较纠结

  • 依赖DOM,可能会与已有样式冲突,如常用的clearfix


3、阴影


.shadow {

-webkit-box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);

box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);

}


没觉得这个方法好用,模拟的效果差强人意,颜色也不好配置,不推荐


4、0.5px


终于等来了0.5px,虽然只有IOS8+才支持


// IOS8 hairline

.hairline(@color, @style:solid) {

@media (-webkit-min-device-pixel-ratio: 2) {

border: 0.5px @style @color;

}

}


优点:


  • “原生”,支持圆角~


缺点:

  • 目前只有IOS8+才支持,在IOS7及其以下、安卓系统都是显示为0px


5、viewport&&rem


再谈mobile web retina 下 1px 边框解决方案介绍了viewport结合rem解决设备像素比的问题,即让我们像以前写1倍像素那样写页面。


如在devicePixelRatio=2下设置<meta>:


<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">


再设置rem,假设header的高度是30px(设备像素比为1的情况):


html {

font-size: 20px;

}

header {

height: 3rem;

}


没有具体实践过,不知道有神马坑~


PS:淘宝、美团移动端页面都是采用这个方式实现的


6、border-image


使用的背景图片:


代码:


.border-image-1px {

border-width: 1px 0px;

-webkit-border-image: url(border.png) 2 0 stretch;

border-image: url(border.png) 2 0 stretch;

}


优点:

  • 额,,,


缺点:

  • 大小、颜色更改不灵活

  • 放到PS里面看边框,是有点模糊的(因为带有颜色部分是1px,在retina屏幕上拉伸到2px肯定会有点模糊)


总结


1、0.5px,相信浏览器肯定是会慢慢支持的;目前而言,如果能用的话,可以hack一下;

2、阴影,border-image的方案不建议使用(用了你就知道。。。)

3、背景图片和缩放可以在项目中配合使用,如单个线条使用缩放,四条框用背景图片模拟,额,如果要圆角的话,无能无力了


其他


  • 再谈mobile web retina 下 1px 边框解决方案

  • 使用border-image实现类似iOS7的1px底边


Demo


1px Demo – jsbin:http://jsbin.com/witida/1/edit?html,css,output



前端大全

微信号:FrontDev

打造东半球最好的 前端技术 微信号

--------------------------------------

商务合作QQ:2302462408

招聘和猎头服务QQ:2302462408

投稿网址:top.jobbole.com





 
前端大全 更多文章 5个典型的JavaScript面试题(上) Limu:JavaScript的那些书 Web开发:我希望得到的编程学习路线图 JavaScript基础工具清单 常用排序算法之JavaScript实现
猜您喜欢 perl语言十分钟入门【零基础可入】 看看国外的JavaScript题目,你能全部做对吗? Code Review最佳实践 R中的数据结构——列表 Python通过多帧静态图像制作GIF动态图像