作者:百度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, @top 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, @w 100%, 100% @w, @w 100%;
background-repeat: no-repeat;
background-position: top, right top, bottom, left top;
}
}
這段程式碼可能是從網上找到的出現最頻繁的程式碼了,但是這樣寫是有相容問題的,
測試小米2自帶瀏覽器、手機百度、百度瀏覽器都顯示不出上邊框,如圖:
測試小米2 chrome瀏覽器正常,如圖:
這種情況我們會考慮是不是沒有寫瀏覽器字首-webkit-的原因,好,我們加上:
background-image:
-webkit-linear-gradient(180deg, @top, @top 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, @top 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, @top 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下設定:
再設定rem,假設essay-header的高度是30px(裝置畫素比為1的情況):
html {
font-size: 20px;
}
essay-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