移动端1px解决方案

栏目: CSS · 发布时间: 6年前

内容简介:移动端web项目越来越多,设计师对于UI的要求也越来越高,比如1px 的边框。在这个是真的1像素那么为什么会产生这个问题呢?主要是跟一个东西有关,DPR(devicePixelRatio) 设备像素比,它是默认缩放为100%的情况下,设备像素和CSS像素的比值。

移动端web项目越来越多,设计师对于UI的要求也越来越高,比如1px 的边框。在 高清屏 下,移动端的1px 会很粗。 比如,这个是假的1像素

移动端1px解决方案

这个是真的1像素

移动端1px解决方案

一、产生原因

那么为什么会产生这个问题呢?主要是跟一个东西有关,DPR(devicePixelRatio) 设备像素比,它是默认缩放为100%的情况下,设备像素和CSS像素的比值。

window.devicePixelRatio=物理像素 /CSS像素
复制代码

目前主流的屏幕DPR=2 (iPhone 8),或者3 (iPhone 8 Plus)。拿2倍屏来说,设备的物理像素要实现1像素,而DPR=2,所以css 像素只能是 0.5。一般设计稿是按照750来设计的,它上面的1px是以750来参照的,而我们写css样式是以设备375为参照的,所以我们应该写的0.5px就好了啊! 试过了就知道,iOS 8+系统支持,安卓系统不支持。

二、解决方案

1、WWDC对iOS统给出的方案

推荐指数:**

在 WWDC大会上,给出来了1px方案,当写 0.5px的时候,就会显示一个物理像素宽度的 border,而不是一个css像素的 border。 所以在iOS下,你可以这样写。

border:0.5px solid #E5E5E5
复制代码

可能你会问为什么在3倍屏下,不是0.3333px 这样的?经过我测试,在Chrome上模拟iPhone 8Plus,发现小于0.46px的时候是显示不出来。

总结:

  • 优点:简单,没有副作用

  • 缺点:支持iOS 8+,不支持安卓。后期安卓follow就好了。

    2、使用边框图片

    推荐指数:**

    border: 1px solid transparent;
      border-image: url('./../../image/96.jpg') 2 repeat;
    复制代码

    图片自己随便截图的,建议自己做一张图片

移动端1px解决方案

图片的颜色就是此后border的颜色

这个方法在W3CPlus 上的例子讲的非常细致 www.w3cplus.com/content/css…

总结:

  • 优点:没有副作用

  • 缺点:border颜色变了就得重新制作图片;圆角会比较模糊。

    3、使用box-shadow实现

    推荐指数:***

    先复习一下box-shadow,看一下MDN 上的这篇就够了 developer.mozilla.org/zh-CN/docs/… 。 再看一下效果

移动端1px解决方案

代码是怎样实现的呢?

box-shadow: 0  -1px 1px -1px #e5e5e5,   //上边线
            1px  0  1px -1px #e5e5e5,   //右边线
            0  1px  1px -1px #e5e5e5,   //下边线
            -1px 0  1px -1px #e5e5e5;   //左边线
复制代码

前面两个值 x,y 主要控制显示哪条边,后面两值控制的是阴影半径、扩展半径。 其实方法可以到这个地址线上尝试一下 。

总结

  • 优点:使用简单,圆角也可以实现

  • 缺点:模拟的实现方法,仔细看谁看不出来这是阴影不是边框。

    4、使用伪元素

    推荐指数:****

    这个方法是我使用最多的,做出来的效果也是非常棒的,直接上代码。

    1 条border

    .setOnePx{
      position: relative;
      &::after{
        position: absolute;
        content: '';
        background-color: #e5e5e5;
        display: block;
        width: 100%;
        height: 1px; /*no*/
        transform: scale(1, 0.5);
        top: 0;
        left: 0;
      }
    }
    复制代码

    可以看到,将伪元素设置绝对定位,并且和父元素的左上角对齐,将width 设置100%,height设置为1px,然后进行在Y方向缩小 0.5倍

    4 条border

    .setBorderAll{
         position: relative;
           &:after{
               content:" ";
               position:absolute;
               top: 0;
               left: 0;
               width: 200%;
               height: 200%;
               transform: scale(0.5);
               transform-origin: left top;
               box-sizing: border-box;
               border: 1px solid #E5E5E5;
               border-radius: 4px;
          }
        }
    复制代码

    同样为伪元素设置绝对定位,并且和父元素左上角对其。将伪元素的长和宽先放大2倍,然后再设置一个边框,以左上角为中心,缩放到原来的 0.5倍 总结:

  • 优点:全机型兼容,实现了真正的1px,而且可以圆角。

  • 缺点:暂用了after 伪元素,可能影响清除浮动。

    5、设置viewport的scale值

    推荐指数:*****

    这个解决方案是利用viewport+rem+js 实现的。 参考了网上的一个例子 移动端1像素边框问题的解决方案 ,自己手动实现了一下。

    移动端1px解决方案

    效果不错。 上代码

    <html>
      <head>
          <title>1px question</title>
          <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
          <meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">        
          <style>
              html {
                  font-size: 1px;
              }            
              * {
                  padding: 0;
                  margin: 0;
              }
              .top_b {
                  border-bottom: 1px solid #E5E5E5;
              }
    
              .a,.b {
                          box-sizing: border-box;
                  margin-top: 1rem;
                  padding: 1rem;                
                  font-size: 1.4rem;
              }
    
              .a {
                  width: 100%;
              }
    
              .b {
                  background: #f5f5f5;
                  width: 100%;
              }
          </style>
          <script>
              var viewport = document.querySelector("meta[name=viewport]");
              //下面是根据设备像素设置viewport
              if (window.devicePixelRatio == 1) {
                  viewport.setAttribute('content', 'width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no');
              }
              if (window.devicePixelRatio == 2) {
                  viewport.setAttribute('content', 'width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no');
              }
              if (window.devicePixelRatio == 3) {
                  viewport.setAttribute('content', 'width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');
              }
              var docEl = document.documentElement;
              var fontsize = 32* (docEl.clientWidth / 750) + 'px';
              docEl.style.fontSize = fontsize;
          </script>
      </head>
      <body>
          <div class="top_b a">下面的底边宽度是虚拟1像素的</div>
          <div class="b">上面的边框宽度是虚拟1像素的</div>
      </body>
    </html>
    复制代码

    总结

  • 优点:全机型兼容,直接写 1px 不能再方便

  • 缺点:适用于新的项目,老项目可能改动大

    三、踩过的坑

    一部血泪史。。。。征服不了UI,只能征服自己。

    1、使用 伪元素 方法,伪类里面再设置伪元素,可以选择到吗?

    看图,需要改中间的竖线

    移动端1px解决方案

    上代码

    &:nth-child(2){
          //border-color: #e5e5e5 !important;
            border: 0;
          position: relative;
          &:after{
            position: absolute;
            content: '';
            background-color: #e5e5e5;
            display: block;
            width: 100%;
            height: 1px; /*no*/
            transform: scale(1, 0.5);
            top: 0;
          }
        }
    复制代码

    然而上面代码展示出来的样式是这样的

    移动端1px解决方案

    为什么中间的竖线没有了?!最初我以为在伪类下面,再写伪元素after,可能会拿不到。

    移动端1px解决方案

    看到这里发现,是有after伪元素的,但是好像位置不对,跑到上面去了。我是想要竖线的,到底什么原因呢?最后在安哥的指导找了一种方法解决了这个问题,才明白其中的真相。

    原来是我的width 和 height 设置的有问题,对于竖线,应该是width =1px,height=100%,然后再缩放 X 方向 0.5倍 ,这样竖线就出来了;同样,设置水平线,应该是width=100%,height=1px,然后再缩放Y方向 0.5倍

知道了原因,再也不担心写错了。

&:nth-child(2){
        position: relative;
        &:after{
          position: absolute;
          content: '';
          top: 0;
          left: 0;
          width: 1px;
          height: 100%;
          transform: scaleX(0.5);
          background: #e5e5e5;
          transform-origin: 0 0;
        }
      }
复制代码

这样是可以的,

&:nth-child(2){
        position: relative;
        &:after{
          content:" ";
          position:absolute;
          top: 0;
          left: 0;
          width: 200%;
          height: 200%;
          transform: scale(0.5);
          transform-origin: left top;
          box-sizing: border-box;
          border-left: 1px solid #E5E5E5;
        }
      }
复制代码

这样也是可以的。

2、为什么还是拿不到 伪元素

我以为知道了上面的方法就可以快快乐乐的写1像素 border 了,然而马上又怀疑自己了。

移动端1px解决方案
上面这个输入框的1像素,需要的所有的border都是1px,我使用了宽高放大200%后再缩小 0.5倍

的方法。

移动端1px解决方案
这就奇怪了,同样的方法在别的地方都有效的,为什么在这里不显示了。找了好久,最后找到这篇文章 使用 CSS 伪元素需要注意的

,然后发现:

移动端1px解决方案

所以不显示的原因找到了,==输入框Textarea不支持伪元素==、 没办法了,伪元素的方法不能用,只能使用其他的方法了。

四、总结

总结一下,新项目最好使用的是 设置viewport的scale值 ,这个方法兼容性好,后期写起来方便。老项目的话,改起来可能比较多,用的比较多的方法就是 伪元素+transform 的方法。 其他的背景图片,阴影的方法毕竟还是不太灵活,而且兼容性不好。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Compilers

Compilers

Alfred V. Aho、Monica S. Lam、Ravi Sethi、Jeffrey D. Ullman / Addison Wesley / 2006-9-10 / USD 186.80

This book provides the foundation for understanding the theory and pracitce of compilers. Revised and updated, it reflects the current state of compilation. Every chapter has been completely revised ......一起来看看 《Compilers》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

html转js在线工具
html转js在线工具

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具