移動(dòng)端1px解決方案總匯

DPR = 設(shè)備像素 /?css像素(某一方向上)
這句話看起來很難理解,可以結(jié)合下面這張圖(1px在各個(gè)DPR上面的展示),一般我們h5拿到的設(shè)計(jì)稿都是750px的,但是如果在DPR為2的屏幕上,手機(jī)的最小像素卻是要用2 * 2px來進(jìn)行繪制,這也就導(dǎo)致了為什么1px會(huì)比較粗了。
1px問題產(chǎn)生的原因
從移動(dòng)端的角度說個(gè)具體的場景,以iphone6為例。
iphone6的屏幕寬度為375px,設(shè)計(jì)師做的視覺稿一般是750px,也就是2x,這個(gè)時(shí)候設(shè)計(jì)師在視覺稿上畫了1px的邊框,于是你就寫了“border-width:1px”,so...1px邊框問題產(chǎn)生了。
對設(shè)計(jì)師來說它的1px是相對于750px的(物理像素),對你來說你的1px是相對于375px的(css像素)“實(shí)際上你應(yīng)該是border-width:0.5px”。
解決方法
解決辦法有很多種,在這里幫大家整理常用的解決方法:
(1)0.5px實(shí)現(xiàn)??
2014年的 WWDC,“設(shè)計(jì)響應(yīng)的Web體驗(yàn)” 一講中,Ted O’Connor 講到關(guān)于“retina hairlines”(retina 極細(xì)的線):在retina屏上僅僅顯示1物理像素的邊框,開發(fā)者應(yīng)該如何處理呢。??
// 正常屏幕.border { border: 1px solid black; }// retina屏幕使用媒體查詢(-webkit-min-device-pixel-ratio: 2) {.border { border-width: 0.5px }}
但是,問題是 retina 屏的瀏覽器可能不認(rèn)識0.5px的邊框,將會(huì)把它解釋成0px,沒有邊框。包括 iOS 7 和 之前版本,OS X Mavericks 及以前版本,還有 Android 設(shè)備。
解決方案是通過 JavaScript 檢測瀏覽器能否處理0.5px的邊框,如果可以,給元素添加個(gè)class。
// js代碼,腳本應(yīng)該放在內(nèi), 如果在里面運(yùn)行,需要包裝$(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實(shí)現(xiàn)
.border{border-width: 1px;border-image: url(border.gif) 2 repeat;}
缺點(diǎn)是改邊框顏色時(shí)要改圖片,不是很方便。
(3)用多背景漸變實(shí)現(xiàn)
設(shè)置1px的漸變背景,50%有顏色,50%透明。缺點(diǎn)是圓角沒法實(shí)現(xiàn)。
.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模擬邊框?qū)崿F(xiàn)
缺點(diǎn)是顏色不好處理,有陰影出現(xiàn)。
.hairlines li {border: none;box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);}
(5)通過 viewport + rem 實(shí)現(xiàn)
將border設(shè)置為1px,然后將頁面根據(jù)設(shè)備的dpr縮小相應(yīng)的倍數(shù),接著將rem放大相應(yīng)的倍數(shù),這樣頁面中只有1px的邊框縮小了,而其他內(nèi)容經(jīng)過縮小和擴(kuò)大,還是原來的狀態(tài)。(rem元素大小不變,僅僅是px元素會(huì)根據(jù)dpr進(jìn)行縮放)。
(6)使用偽類 + transform實(shí)現(xiàn)
原理是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 縮小一半,原先的元素相對定位,新做的 border 絕對定位。
單個(gè)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;}
樣式使用的時(shí)候,也要結(jié)合?js?代碼,判斷是否 Retina 屏
if(window.devicePixelRatio && devicePixelRatio >= 2){document.querySelector('ul').className = 'hairlines';}
本文完~

