解決移動端1px邊框問題的幾種方法


解決移動端1px邊框問題的幾種方法

本文介紹了解決移動端1px邊框問題的5種方法。當然了,在這之前先整理了與這些方法相關的知識:物理像素、設備獨立像素、設備像素比和viewport

物理像素、設備獨立像素和設備像素比

CSS中我們一般使用px作為單位,需要注意的是,CSS樣式里面的px和物理像素並不是相等的。CSS中的像素只是一個抽象的單位,在不同的設備或不同的環境中,CSS中的1px所代表的物理像素是不同的。在PC端,CSS1px一般對應着電腦屏幕的1個物理像素,但在移動端,CSS1px等於幾個物理像素。

物理像素(physical pixel)

物理像素又被稱為設備像素、設備物理像素,它是顯示器(電腦、手機屏幕)最小的物理顯示單位,每個物理像素由顏色值和亮度值組成。所謂的一倍屏、二倍屏(Retina)、三倍屏,指的是設備以多少物理像素來顯示一個CSS像素,也就是說,多倍屏以更多更精細的物理像素點來顯示一個CSS像素點,在普通屏幕下1個CSS像素對應1個物理像素,而在Retina屏幕下,1個CSS像素對應的卻是4個物理像素(參照下文田字示意圖理解)。

設備獨立像素(device-independent pixel)

設備獨立像素又被稱為CSS像素,是我們寫CSS時所用的像素,它是一個抽像的單位,主要使用在瀏覽器上,用來精確度量Web頁面上的內容。

設備像素比(device pixel ratio)

設備像素比簡稱為dpr,定義了物理像素和設備獨立像素的對應關系:設備像素比 = 物理像素 / 設備獨立像素

簡單點說就是:CSS1px等於幾個物理像素;除了和屏幕像素密度dpr有關,還和用戶縮放有關系。例如,當用戶把頁面放大一倍,那么CSS1px所代表的物理像素也會增加一倍;反之把頁面縮小一倍,CSS1px所代表的物理像素也會減少一倍。關於這點,在文章后面的1px細線問題部分還會講到。

image-20200522193027016

我們可以發現,在同樣的大小下,2dpr的屏幕時普通屏幕像素點的4倍,3dpr的屏幕時普通屏幕像素點的9倍。這就是retina屏幕用了都說好的原因(清晰)。

1px細線問題

在上文我們已經知道,CSS像素為1px寬的直線,對應的物理像素是不同的,可能是2px或者3px,而設計師想要的1px寬的直線,其實就是1物理像素寬。而設計師要的實際1px的邊框就是下面這種情況:

image-20200522193227067

對於CSS而言,可以認為是border: 0.5px;,這是多倍屏下能顯示的最小單位。然而,並不是所有手機瀏覽器都能識別border: 0.5px,有的系統里,0.5px會被當成為0px處理,那么如何1px細線問題呢?

解決方法

1.使用border-image實現

准備一張符合你要求的border-image

image-20200522193834965

樣式設置:

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

上文是把border設置在邊框的底部,所以使用的圖片是2px高,上部的1px顏色為透明,下部的1px使用視覺規定的border的顏色。

優點:

  • 可以設置單條、多條表框。

缺點:

  • 更換顏色和樣式麻煩,需要更改圖片;
  • 某些設備上會模糊。

2.使用background-image實現

background-imageborder-image的方法一樣,你要先准備一張符合你要求的圖片。然后將邊框模擬在背景上。
樣式設置:

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

優缺點與border-image一樣;

3.多背景漸變實現

background-image方案類似,只是將圖片替換為css3漸變。設置1px的漸變背景,50%有顏色,50%透明。
樣式設置:

.background-gradient-1px {
  background:
    linear-gradient(#000, #000 100%, transparent 100%) left / 1px 100% no-repeat,
    linear-gradient(#000, #000 100%, transparent 100%) right / 1px 100% no-repeat,
    linear-gradient(#000,#000 100%, transparent 100%) top / 100% 1px no-repeat,
    linear-gradient(#000,#000 100%, transparent 100%) bottom / 100% 1px no-repeat
}
/* 或者 */
.background-gradient-1px{
  background:
    -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) left / 1px 100% no-repeat,
    -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) right / 1px 100% no-repeat,
    -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) top / 100% 1px no-repeat,
    -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) bottom / 100% 1px no-repeat
}

優點:

  • 可以實現單條、多條邊框
  • 邊框的顏色隨意設置

缺點:

  • 代碼量不少
  • 圓角沒法實現
  • 多背景圖片有兼容性問題

4.使用box-shadow模擬邊框

利用css 對陰影處理的方式實現0.5px的效果
樣式設置:

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

優點:代碼少,兼容性好。缺點:邊框有陰影,顏色變淺。

上面四種方式效果並不是太好;

5.偽元素+transform

構建1個偽元素, border1px, 再以transform縮放到50%

對於老項目,有沒有什么辦法能兼容1px的尷尬問題了,個人認為偽類+transform是比較完美的方法了。
原理是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,並將 transformscale 縮小一半,原先的元素相對定位,新做的 border 絕對定位。
單條border樣式設置:

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

四條boder樣式設置:

.scale-1px{
  position: relative;
  margin-bottom: 20px;
  border:none;
}
.scale-1px:after{
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid #000;
  -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;
}

最好在使用前也判斷一下,結合 JS 代碼,判斷是否 Retina 屏:

if(window.devicePixelRatio && devicePixelRatio >= 2){
  document.querySelector('ul').className = 'scale-1px';
}

優點:可以滿足所有場景,且修改靈活。缺點:對於已使用偽類的元素(例如clearfix)要多層嵌套。

6.viewport + rem 實現

同時通過設置對應viewportrem基准值,這種方式就可以像以前一樣輕松愉快的寫1px了。
devicePixelRatio = 2 時,輸出viewport

<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

devicePixelRatio = 3 時,輸出viewport

<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">

這種兼容方案相對比較完美,適合新的項目,老的項目修改成本過大。

優點:

  • 所有場景都能滿足
  • 一套代碼,可以兼容基本所有布局

缺點:

  • 老項目修改代價過大,只適用於新項目


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM