最近一个月都在准备校招,因此没什么时间写博客。今天想写的问题来自于网易一面的时候,面试官问我如何在移动端的页面上画一条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) }
这篇文章从国庆开始断断续续地写,到最后一天总算是写完了,这段时间整我的心态经历了一些变化,主要表如今对待技术比之前更加踏实了,不管如何但愿本身能坚持写博客,坚持学习前端,相信总能找到一个理想的工做的,加油!