最近一個月都在準備校招,因此沒什麼時間寫博客。今天想寫的問題來自於網易一面的時候,面試官問我如何在移動端的頁面上畫一條1px的線。這個問題我模糊地記得以前看過相關文章,可是我清楚地記得當時本身腦子一片空白。是的,一面掛了,可是這個問題一直在我回來的路上不斷想起,因此今天我就要解決這個問題,來看看有什麼解決方案吧~javascript
這是淘寶的flexible提出的解決方案,其核心就是根據window.devicePixelRatio(dpr)的值動態改變viewport的縮放,核心代碼以下(有刪減):css
if (!dpr && !scale) { var isAndroid = win.navigator.appVersion.match(/android/gi); var isIPhone = win.navigator.appVersion.match(/iphone/gi); var devicePixelRatio = win.devicePixelRatio; if (isIPhone) { // iOS下,對於2和3的屏,用2倍的方案,其他的用1倍方案 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ dpr = 2; } else { dpr = 1; } } else { // 其餘設備下,仍舊使用1倍的方案 dpr = 1; } scale = 1 / dpr; } if (!metaEl) { metaEl = doc.createElement('meta'); metaEl.setAttribute('name', 'viewport'); metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); if (docEl.firstElementChild) { docEl.firstElementChild.appendChild(metaEl); } else { var wrap = doc.createElement('div'); wrap.appendChild(metaEl); doc.write(wrap.innerHTML); } }
這個方案只對iOS的Retina屏幕作了處理,而沒有管安卓的Retina屏幕,緣由能夠看《再談Retina下1px的解決方案》這篇文章。使用了flexible以後直接寫1px就能實現效果,可是最新的2.0好像放棄了這種縮放的方案,對於1px的處理則變成了border-image或者background-image,詳細的能夠看《再聊移動端頁面的適配》。html
這裏再簡單談一下這種viewport縮放的原理:前端
首先一開始寫移動端的時候,我是直接加一個meta標籤 <meta name=viewport content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no">
,這個meta標籤使得頁面寬度等於設備寬度,頁面的縮放默認爲1,且用戶不能縮放,後來看到一篇文章講viewport計算是這樣的:java
viewport的默認寬度是980px;設置了initial-scale則寬度是device-width/initial-scale;設置了width則寬度等於width的值;同時設置了initial-scale和width則寬度取二者中較大的一個。android
上面的結論我在PC端谷歌瀏覽器的設備模擬器裏證明了有效,可是安卓和iOS真機並無試過。git
這個方案也是WeUI正在用的,核心思想是使用transform的scale來總體縮放,若是你想畫一條1px的線,就能夠直接用github
div { height: 1px; background: #000; transform: scaleY(0.5); transform-origin: 0 0; }
理論上在dpr爲2時就是scaleY(0.5),在dpr爲3時就是scaleY(0.333),可是我注意到WeUI並無針對其餘dpr的作特殊處理,多是由於在iPhone6(dpr=2)和iPhone6 Plus(dpr=3)中看起來差異不大吧。web
若是你想給一個元素加一個1px的邊框能夠利用到僞元素,在這個方案下邊框加圓角也很容易實現,具體代碼以下:面試
div:after { content: " "; width: 78px; height: 38px; border-radius: 4px; border: 1px solid #000; transform: scale(0.5, 0.5); transform-origin: 0 0; position: absolute; }
這種是AlloyTeam的《CSS 實現相似原生效果的 1px 邊框》這篇文章上看到的,代碼寫起來挺簡單,可是要本身製做圖片,並且圓角也很差弄,若是改了顏色就要對圖片處理,因此不是很好的方案。
這個顏色很差弄,因此效果也不是很好。
div { border: none; box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5); }
div { border: 1px solid #000; } @media (-webkit-min-device-pixel-ratio: 2) { div { border: .5px solid #000; } }
安卓和iOS7以前版本碰到0.5px直接就解析成0px了,可是這一特性也是能夠利用的,在最新的flexible中就有對0.5px進行判斷的代碼:
// detect 0.5px supports if (dpr >= 2) { var fakeBody = document.createElement('body') var testElement = document.createElement('div') testElement.style.border = '.5px solid transparent' fakeBody.appendChild(testElement) docEl.appendChild(fakeBody) if (testElement.offsetHeight === 1) { docEl.classList.add('hairlines') } docEl.removeChild(fakeBody) }
這篇文章從國慶開始斷斷續續地寫,到最後一天總算是寫完了,這段時間整我的心態經歷了一些變化,主要表如今對待技術比之前更加踏實了,不管如何但願本身能堅持寫博客,堅持學習前端,相信總能找到一個理想的工做的,加油!