移動端1px解決方案總彙
1px問題產生的原因
從移動端的角度說個具體的場景,以iphone6為例。
iphone6的螢幕寬度為375px,設計師做的視覺稿一般是750px,也就是2x,這個時候設計師在視覺稿上畫了1px的邊框,於是你就寫了“border-width:1px”,so...1px邊框問題產生了。
對設計師來說它的1px是相對於750px的(物理畫素),對你來說你的1px是相對於375px的(css畫素)“實際上你應該是border-width:0.5px”。
解決方法
解決辦法有很多種,在這裡幫大家整理常用的解決方法:
(1)0.5px實現
2014年的 WWDC,“設計響應的Web體驗” 一講中,Ted O’Connor 講到關於“retina hairlines”(retina 極細的線):在retina屏上僅僅顯示1物理畫素的邊框,開發者應該如何處理呢。// 正常螢幕
.border { border: 1px solid black; }
// retina螢幕使用媒體查詢
@media (-webkit-min-device-pixel-ratio: 2) {
.border { border-width: 0.5px }
}
但是,問題是 retina 屏的瀏覽器可能不認識0.5px的邊框,將會把它解釋成0px,沒有邊框。包括 iOS 7 和 之前版本,OS X Mavericks 及以前版本,還有 Android 裝置。
解決方案是通過JavaScript檢測瀏覽器能否處理0.5px的邊框,如果可以,給<html>元素添加個class。
// js程式碼,指令碼應該放在<body>內, 如果在<head>裡面執行,需要包裝$(document).ready(function() { })
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);
}
// css程式碼
div {
border: 1px solid #bbb;
}
.hairlines div {
border-width: 0.5px;
}
(2)使用border-image實現
.border{
border-width: 1px;
border-image: url(border.gif) 2 repeat;
}
缺點是改邊框顏色時要改圖片,不是很方便。
(3)用多背景漸變實現
設定1px的漸變背景,50%有顏色,50%透明。缺點是圓角沒法實現。
.border {
background:
linear-gradient(180deg, black, black 50%, transparent 50%) top left / 100% 1px no-repeat,
linear-gradient(90deg, black, black 50%, transparent 50%) top right / 1px 100% no-repeat,
linear-gradient(0, black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat,
linear-gradient(-90deg, black, black 50%, transparent 50%) bottom left / 1px 100% no-repeat;
}
(4)使用box-shadow模擬邊框實現
缺點是顏色不好處理,有陰影出現。
.hairlines li {
border: none;
box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);
}
(5)通過 viewport + rem 實現
將border設定為1px,然後將頁面根據裝置的dpr縮小相應的倍數,接著將rem放大相應的倍數,這樣頁面中只有1px的邊框縮小了,而其他內容經過縮小和擴大,還是原來的狀態。(rem元素大小不變,僅僅是px元素會根據dpr進行縮放)
https://www.houdianzi.com/suzhoulogo/ 蘇州logo設計
(6)使用偽類 + transform實現
原理是把原先元素的 border 去掉,然後利用 :before 或者 :after 重做 border ,並 transform 的 scale 縮小一半,原先的元素相對定位,新做的 border 絕對定位。
單個border
.hairlines li{
position: relative;
border:none;
}
.hairlines li:after{
content: '';
position: absolute;
left: 0;
background: #000;
width: 100%;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
四條 border
.hairlines li{
position: relative;
margin-bottom: 20px;
border:none;
}
.hairlines li: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;
}
樣式使用的時候,也要結合js程式碼,判斷是否 Retina 屏
if(window.devicePixelRatio && devicePixelRatio >= 2){
document.querySelector('ul').className = 'hairlines';
}