移动端1px解决方案

摘要:
移动端1px解决方案作者:empty@毛豆前端前言移动端web项目越来越多,设计师对于UI的要求也越来越高,比如1px的边框。在高清屏下,移动端的1px会很粗。参考了网上的一个例子移动端1像素边框问题的解决方案,自己手动实现了一下。

移动端1px解决方案第1张

移动端1px解决方案

作者:empty@毛豆前端

前言

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

移动端1px解决方案第2张这个是真的1像素 移动端1px解决方案第3张

一、产生原因

那么为什么会产生这个问题呢?主要是跟一个东西有关,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解决方案第4张图片的颜色就是此后border的颜色

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

总结:

  • 优点:没有副作用

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

    3、使用box-shadow实现

    推荐指数:***

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

移动端1px解决方案第5张代码是怎样实现的呢?
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;
         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;
                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解决方案第6张效果不错。 上代码
    <html>
      <head>
          <title>1px question</title>
          <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
          <meta name="viewport"   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 {
                   100%;
              }
    
              .b {
                  background: #f5f5f5;
                   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解决方案第7张上代码
        &:nth-child(2){
          //border-color: #e5e5e5 !important;
            border: 0;
          position: relative;
          &:after{
            position: absolute;
            content: '';
            background-color: #e5e5e5;
            display: block;
             100%;
            height: 1px; /*no*/
            transform: scale(1, 0.5);
            top: 0;
          }
        }
    复制代码

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

    移动端1px解决方案第8张为什么中间的竖线没有了?!最初我以为在伪类下面,再写伪元素after,可能会拿不到。移动端1px解决方案第9张看到这里发现,是有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;
           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;
           200%;
          height: 200%;
          transform: scale(0.5);
          transform-origin: left top;
          box-sizing: border-box;
          border-left: 1px solid #E5E5E5;
        }
      }
复制代码

这样也是可以的。

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

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

移动端1px解决方案第10张上面这个输入框的1像素,需要的所有的border都是1px,我使用了宽高放大200%后再缩小0.5倍的方法。移动端1px解决方案第11张这就奇怪了,同样的方法在别的地方都有效的,为什么在这里不显示了。找了好久,最后找到这篇文章使用 CSS 伪元素需要注意的,然后发现:移动端1px解决方案第12张所以不显示的原因找到了,==输入框Textarea不支持伪元素==、 没办法了,伪元素的方法不能用,只能使用其他的方法了。

四、总结

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

免责声明:文章转载自《移动端1px解决方案》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇pytorch MNIST加载已下载的数据集出现问题及解决方法Vue 项目添加单元测试发现的问题及解决下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

元素跟随着滚动条运动

有这种情况,页面中的某些元素需要跟随滚动条运动,位置一直在页面中的某个位置; 思路: 当页面滚动的时候,一直获取滚动条距离顶部的距离,当顶部的距离等于某个数值的时候,直接开始改变这个元素的position的值为fixed,不等于这个数值的时候为relative; 注意的是需要在html中写一个和这个元素一样的元素,不等于数值的这个元素为display:no...

Android二维码功能实现

最近二维码真是越来越火了,随便电视上、网络上、商场里,到处都是二维码。而内嵌二维码扫描功能的软件也越来越多,QQ、微信、UC浏览器等等应用都可以对着二维码扫一扫,感觉我们自己的应用里不加上二维码扫描功能,都跟不上时代潮流了。所以今天我就将带着大家一起,在我们自己的程序里加入二维码扫描的功能。 不过,二维码功能如果真要做起来还是非常复杂的,从零开始实现不太现...

HOG 特征提取算法(原理篇)

在计算机视觉中人们设计了很多算法来提取空间特征,并利用图像梯度信息来识别物体。 其中一种技术叫做 HOG,也即方向梯度直方图(Histogram of Oriented Gradient)。方向梯度直方图听着太高深了,我们先来讲一下这些术语。 直方图就是数据分布的一种图形表现,看起来有点像柱形图,其柱形有不同的高度,每个柱形代表一组处于一定值范围的数据...

移动平台的meta标签-----神奇的功效

 对于桌面平台web布局中大家对meta标签再熟悉不过了,它永远位于 head 元素内部,对做SEO的朋友一定对meta有种特殊的感情吧,今天我们就来说说移动平台的meta标签,在移动平台meta标签究竟有哪些神奇的功效呢? 1、Meta 之 viewport 说到移动平台meta标签,那就不得不说一下viewport了,那么什么是viewport呢?vi...

Android 高级UI设计笔记23:Android 夜间模式之 两种常用方法(降低屏幕亮度+替换theme)

1. 夜间模式  所谓的夜间模式,就是能够根据不同的设定,呈现不同风格的界面给用户,而且晚上看着不伤眼睛。特别是一些新闻类App实现夜间模式是非常人性化的,增强用户体验。 2. 我根据网上的资料 以及自己代码亲测,总结如下两种方法: (1)降低屏幕亮度 (2)替换theme 3. 夜间模式之 降低屏幕亮度: (1)创建一个Android工程,命名为"夜间模...

检测当前运行环境——移动端与PC端。

方法1: $(function checkBrowser(){ var browser={      versions:function(){             var u = navigator.userAgent, app = navigator.appVersion; return { //移动终端浏览器版本信息                ...