7 種方案解決移動端1px邊框的問題

林恒發表於2024-07-05

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

7 種方案解決移動端1px邊框的問題

造成邊框變粗的原因

css中的1px並不等於移動裝置的1px,這是由不同手機由不同畫素密度,在window物件中有一個devicePixelRatio屬性,他可以反應css中畫素與裝置的畫素比

devicePixelRatio 的官方給的定義為: 裝置物理畫素和裝置獨立畫素的比例,也就是devicePixelRatio = 物理畫素 / 獨立畫素。

解決邊框變粗的6種辦法

總結:

  • 根據判斷畫素比大於等於2時,

1、0.5px邊框

if(window.devicePixelRatio && devicePixelRatio>=2){
  var testElem = document.createElement('div')
  testElem.style.border = '.5px solid transparent'
  document.body.appendChild(testElem)
  if(testElem.offsetHeight ==1){
    document.querySelector('html').classList.add('hairlines')
  }
  document.body.removeChild(testElem);
}
// 指令碼放在內聯,如果裡面執行 需要包裝$(document).ready(function(){})
div{
  border: 1px solid #bbb
}
.hairlines div {
  border-width: 0.5px;
}

2、使用border-image實現

準備一張符合要求的border-image

底部邊框

.border-bottom-1px{
  border-width: 0 0 1px 0 ;
  border-image: url(linenew.png) 0 0 2 0 stretch;
  -webkit-border-image: url(linenew.png) 0 0 2 0 stretch;
}

把border設定在底部,圖片2px高,上面1px顏色透明,下面1px使用規定的border顏色

3、使用background-image實現

和border-image實現類似,需要事先準備好圖片

.backround-image-1px{
  background: url(../img/line.png) repeat-x left bottom;
  -wibkit-background-size:100% 1px;
  background-size:100% 1px;
}

缺點:

  • 修改顏色麻煩,需要替換圖片
  • 圓角需要特別處理,邊緣會模糊

4、利用多背景漸變實現

與background-image類似,把圖片改成漸變的背景,一半設定顏色,一半設定透明

.background-gradient-1px{
  background:
    line-gradient(180deg, black,black 50%, transparent 50%) top left / 100% 1px no-repeat;
    line-gradient(90deg, black,black 50%, transparent 50%) top right / 1px 100% no-repeat;
    line-gradient(0, black,black 50%, transparent 50%) bottom right /  100% 1px no-repeat;
    line-gradient(-90deg, black,black 50%, transparent 50%) bottom left / 1px 100% no-repeat;
}
/*或者*/
.background-gradient-1px{
    background: -webkit-gradient(linear,left top, left bottom, color-step(.5,transparent),
                color-step(.5,#c8c7cc), to(#c8c7cc)) left bottom repeat-x;
    background-size: 100% 1px;
}

5、利用box-shadow模擬邊框

css陰影的方式處理

.box-shadow-1px{
  box-shadow: inset 0px -1px 1px -1px #c8c7cc
}

6、viewport + rem 實現

同時透過設定對應的viewport的rem基準值, 解決了1畫素bug

這種方式比較完美,對老版本的修改不友好

優點:所有場景都能滿足,一套程式碼,可以相容所有佈局

缺點:老專案修改代價過大

// 在devicePixlRatio = 1 時, 輸出viewport
<mate name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
      
// 在devicePixlRatio = 2 時, 輸出viewport
<mate name="viewport" content="initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">
  
// 在devicePixlRatio = 3 時, 輸出viewport
<mate name="viewport" content="initial-scale=0.333333,maximum-scale=0.333333,minimum-scale=0.333333,user-scalable=no">



<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width,initial-scale=1,user-scalable=no"
    />
    <title>rem+viewport適配</title>
    <style type="text/css">
      * {
        margin: 0;
        padding: 0;
      }
      #box {
        width: 8rem;
        height: 8rem;
        border: 1px solid #000;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
  </body>
  <script type="text/javascript">
    //獲取dpr
    var dpr = window.devicePixelRatio; // 2
    console.log(dpr, 'dpr+++');
    //比例              // 0.5
    var scale = 1 / dpr;
    var width = document.documentElement.clientWidth; //375
    //3.透過dpr讓元素進行縮放,initial-scale=0.5
    var metaNode = document.querySelector('meta[name="viewport"]');
    metaNode.setAttribute(
      'content',
      'width=device-width,initial-scale=' + scale + ',user-scalable=no'
    );
    var width = document.documentElement.clientWidth; //750
    //4.佈局元素 單位 rem ,反向把縮放比例乘回來  2
    var styleN = document.createElement('style');
    styleN.innerHTML = 'html{font-size: ' + width / 16 + 'px !important;}';
    document.head.appendChild(styleN);
  </script>
</html>

7、使用偽類+transform實現

對於老專案,這種方案比較完美, 原理是把原來的所有邊框去掉,透過偽類崇左border,並且transform的scale縮小一半,原先的單挑border樣式設定

.scale-1px{
  position:relative;
  border:none;
}
.scale-1px:after{
  content: '';
  position:absolute;
  bottom:0;
  background: #000;
  width:100%;
  height:1px;
  transform:scale(0.5);
  transform-origin: 0 0;
}

.scale-1px-top {
  /* border-bottom: 1px solid rgb(229, 229, 229); */
  /* box-shadow: inset 0px -1px 1px -1px #c8c7cc; */
  border:none;
  position:relative;
}
.scale-1px-top:before{
  content: '';
  position: absolute;
  display:block;
  top: 0;
  left: 0;
  width: 200%;
  height: 1px;
  border-top: 1px solid #E7E7E7;
  -webkit-transform: scale(0.5,0.5);
  transform: scale(0.5,0.5);
  -webkit-transform-origin: 0 0;
  transform-origin: 0 0;
}

.scale-1px-bottom {
  /* border-bottom: 1px solid rgb(229, 229, 229); */
  /* box-shadow: inset 0px -1px 1px -1px #c8c7cc; */
  border:none;
  position:relative;
}
.scale-1px-bottom:before{
  content: '';
  position: absolute;
  display:block;
  bottom: -1px;
  left: 0;
  width: 200%;
  height: 1px;
  border-bottom: 1px solid #ccc;
  -webkit-transform: scale(0.5,0.5);
  transform: scale(0.5,0.5);
  -webkit-transform-origin: 0 0;
  transform-origin: 0 0;
}

.borderRadius-1px {
  /* border-bottom: 1px solid rgb(229, 229, 229); */
  /* 圓角(偽類和本體類都需要加border-radius) */
  border-radius:.16rem;
  border:none;
  position:relative;
}
.borderRadius-1px:after{
  /* 圓角(偽類和本體類都需要加border-radius) */
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid #d1d1d1;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  width: 200%;
  height: 200%;
  -webkit-transform: scale(0.5);
  transform: scale(0.5);
  -webkit-transform-origin: left top;
  transform-origin: left top;
  border-radius:.16rem;
}

8 、svg

<svg width=100% height=1   style="position: absolute;bottom: 0;left: 0;">
 <line x1="0" y1="0" x2="1000" y2="0" style="stroke:#E5E5E5;stroke-width:1" />
</svg>

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

7 種方案解決移動端1px邊框的問題

相關文章