阅读 467

CSS 技巧篇(十):1px边框解决方案

一、产生原因

随着移动端的web项目越来越多,设计师的要求也越来越高。在移动端上通过1px实现一条1像素的线时,它并不是真正的1像素,比真正的1像素要粗一点。
那么为什么会产生这个问题呢?主要是跟一个东西有关,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+系统支持,安卓系统不支持。

二、解决方案

2.1 使用小数点方式

.border { border: 1px solid #999 }
@media screen and (-webkit-min-device-pixel-ratio: 2) {
    .border { border: 0.5px solid #999 }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
    .border { border: 0.333333px solid #999 }
}
复制代码
  • 优点:比较方便
  • 缺点:支持iOS 8+,不支持安卓。

2.2 使用伪元素

<span class="border-1px">1像素边框问题</span>

// less
.border-1px{
  position: relative;
  &::before{
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 200%;
    border:1px solid red;
    color: red;
    height: 200%;
    -webkit-transform-origin: left top;
    transform-origin: left top;
    -webkit-transform: scale(0.5);
    transform: scale(0.5);
    pointer-events: none; /* 防止点击触发 */
    box-sizing: border-box;
    @media screen and (min-device-pixel-ratio:3),(-webkit-min-device-pixel-ratio:3){
      width: 300%;
      height: 300%;
      -webkit-transform: scale(0.33);
      transform: scale(0.33);
    }
  }
}
复制代码
  • 优点:直接通过CSS实现,无论是圆角还是直角都可以实现。
  • 缺点:代码量比较多,占有了伪元素。

注意:空元素(不能包含内容的元素)不支持 ::before,::after

  • IE 不支持的元素有:img,input,select,textarea。
  • FireFox 不支持的元素有:input,select,textarea。
  • Chrome 不支持的元素有:input[type=text],textarea。

2.3 使用box-shadow

<span class="border-1px">1像素边框问题</span>

.border-1px{
  box-shadow: 0px 0px 1px 0px red inset;
}
复制代码
  • 优点:直接通过CSS实现,无论是圆角还是直角都可以实现。
  • 缺点:由于是使用阴影的方式,边框线的颜色会比真实颜色淡一点。

2.4 使用border-image

弄出1px像素边框的实质是弄出0.5px这样的边框,所以我们可以利用类似于这样的图片,使得“border-image-slice”为2,那么实际上边框有一半是透明的,即可得到我们想要的“1px边框”

<div class="test">1像素边框</div>
.test{
    border: 1px solid transparent;
    border-image: url('./border-1px.png') 2 repeat;
}
复制代码
  • 优点:其实感觉没啥优点。。。
  • 缺点:修改颜色麻烦, 需要替换图片;圆角需要特殊处理,并且边缘会模糊

2.5 设置viewport的scale值

根据设备像素设置viewport,代码只需要写正常像素就可以了。

<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不能再方便
  • 缺点:适用于新的项目,老项目可能改动大,

三、参考

关注下面的标签,发现更多相似文章
评论