资讯专栏INFORMATION COLUMN

谈一谈移动端1px的问题

qianfeng / 1100人阅读

摘要:今天想写的问题来自于网易一面的时候,面试官问我如何在移动端的页面上画一条的线。上面的结论我在端谷歌浏览器的设备模拟器里证实了有效,但是安卓和真机并没有试过。

起因

最近一个月都在准备校招,所以没什么时间写博客。今天想写的问题来自于网易一面的时候,面试官问我如何在移动端的页面上画一条1px的线。这个问题我模糊地记得之前看过相关文章,但是我清楚地记得当时自己脑子一片空白。是的,一面挂了,但是这个问题一直在我回来的路上不断想起,所以今天我就要解决这个问题,来看看有什么解决方案吧~

动态改变viewport的缩放

这是淘宝的flexible提出的解决方案,其核心就是根据window.devicePixelRatio(dpr)的值动态改变viewport的缩放,核心代码如下(有删减):

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,详细的可以看《再聊移动端页面的适配》。

这里再简单谈一下这种viewport缩放的原理:

首先一开始写移动端的时候,我是直接加一个meta标签 ,这个meta标签使得页面宽度等于设备宽度,页面的缩放默认为1,且用户不能缩放,后来看到一篇文章讲viewport计算是这样的:

viewport的默认宽度是980px;设置了initial-scale则宽度是device-width/initial-scale;设置了width则宽度等于width的值;同时设置了initial-scale和width则宽度取两者中较大的一个。

上面的结论我在PC端谷歌浏览器的设备模拟器里证实了有效,但是安卓和iOS真机并没有试过。

transform: scale(0.5)

这个方案也是WeUI正在用的,核心思想是使用transform的scale来整体缩放,如果你想画一条1px的线,就可以直接用

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)中看起来差别不大吧。

如果你想给一个元素加一个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;
}
其他方案 border-image

这种是AlloyTeam的《CSS 实现类似原生效果的 1px 边框》这篇文章上看到的,代码写起来挺简单,但是要自己制作图片,而且圆角也不好弄,如果改了颜色就要对图片处理,所以不是很好的方案。

box-shadow

这个颜色不好弄,所以效果也不是很好。

div {
  border: none;
  box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);
}
0.5px解决方案
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)
}
小结

这篇文章从国庆开始断断续续地写,到最后一天总算是写完了,这段时间整个人心态经历了一些变化,主要表现在对待技术比以前更加踏实了,无论如何希望自己能坚持写博客,坚持学习前端,相信总能找到一个理想的工作的,加油!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/116655.html

相关文章

  • 来,让我们一谈Normalize.css

    摘要:相比于传统的,是一种现代的为准备的优质替代方案。保护了有价值的默认值通过为几乎所有的元素施加默认样式,强行使得元素有相同的视觉效果。当一个元素在不同的浏览器中有不同的默认值时,会力求让这些样式保持一致并尽可能与现代标准相符合。 本文译自 http://nicolasgallagher.com/about-normalize-css/ 最初发布于我的博客:http://jerr...

    _Zhao 评论0 收藏0
  • 2017-10-09 前日报

    摘要:前端日报精选传送门浏览器性能优化渲染性能在生产中的使用发送推送第期巧用匿名函数重构你的代码中文可持久化数据结构以及结构分享众成翻译学习笔记的模板学习笔记教程的作用域插槽教程移动助手实践一基于的换肤功能掘金网站压力及性能测试一篇 2017-10-09 前端日报 精选 传送门:React Portal浏览器性能优化-渲染性能在生产中的Progressive Web App使用Service...

    WilsonLiu95 评论0 收藏0
  • 一谈JVM垃圾回收

    摘要:这个算法看似不错而且简单,不过存在这一个致命伤当两个对象互相引用的时候,就永远不会被回收于是引用计数算法就永远回收不了这两个对象,下面介绍另一种算法。 前言 ​ 如果要问Java与其他编程语言最大的不同是什么,我第一个想到的一定就是Java所运行的JVM所自带的自动垃圾回收机制,以下是我学习JVM垃圾回收机制整理的笔记,希望能对读者有一些帮助。 哪些内存需要回收?what? ​ ...

    stormzhang 评论0 收藏0
  • 一谈javascript异步

    摘要:从今天开始研究一下的异步相关内容,感兴趣的请关注同期异步系列文章推荐异步中的回调异步与异步之异步之异步之和异步之一异步之二异步实战异步总结归档什么是异步我们知道的单线程的,这与它的用途有关。 从今天开始研究一下javascript的异步相关内容,感兴趣的请关注 同期异步系列文章推荐javascript异步中的回调javascript异步与promisejavascript异步之Prom...

    Sourcelink 评论0 收藏0
  • 一谈浏览器兼容问题

    摘要:浏览器兼容问题什么是浏览器兼容所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况。 浏览器兼容问题 1、什么是浏览器兼容 所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况。 2、浏览器兼容产生的原因 因为不同浏览器使用内核及所支持的HTML等网页语言标准不同; 以及用户客户端的环境不同(如...

    wangzy2019 评论0 收藏0

发表评论

0条评论

qianfeng

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<