移動端的1px問題


布局視口 layout viewport:

手機一般為了容納為桌面瀏覽器設計的網站,默認布局viewport寬度遠大於屏幕的寬度,為了讓用戶看到網站全貌,縮小網站。例如,apple一般將viewport寬度定為980px。主要意義是手機廠商不至於讓自家手機變得可笑,在打開大於980寬度的頁面的時候可以橫向拖動,而不至於擠成一團。可以通過document.documentElement.clientWidth來獲取。

視覺視口 visual viewport:

屏幕的可視區域,即物理像素尺寸,可以通過window.innerWidth來獲取。對於iPhone 6 Plus來說,在加了著名代碼前提下,值是414px,不加的話,值是980px,著名代碼如果改一改width=device-width, initial-scale=1.5,這時值是276px。所以它是一個可變的值。

理想視口 ideal viewport:

最適合移動設備的viewport,ideal viewport的寬度等於移動設備的屏幕寬度

為了讓viewport能夠等於ideal viewport,一般我們會添加meta標簽。width=device-width,initial-scale=1.0的時候,視覺視口的大小。對於iPhone 6 Plus來說,是固定值414px。所以,理想視口就等於設備寬度。

1、什么是1px問題

     移動端css設置1px(如border:1px solid #000;),實際上邊框的寬度比設置的1px要寬

2、移動端1px變寬原因 

   <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

這句話定義了本頁面的viewport的寬度為設備寬度,初始縮放值和最大縮放值都為1,並禁止了用戶縮放. viewport通俗的講是瀏覽器上可用來顯示頁面的區域, 這個區域是可能比屏幕大的.

3、1px解決方案

(1)  用小數寫1px

//這是css方式
.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 } }
//如果使用less/sass的話只是加了1句mixin
//缺點: IOS8下已經支持帶小數的px值,安卓與低版本IOS不適用, 這個或許是未來的標准寫法, 現在不做指望
//這是JavaScript方式
<
body> <div id="main" style="border: 1px solid #000000;"></div> </body> <script type="text/javascript"> if (window.devicePixelRatio && devicePixelRatio >= 2) { var main = document.getElementById('main'); main.style.border = '.5px solid #000000'; } </script>

//優點: 簡單

//缺點: 兼容性差,目前之余IOS8+才支持,在IOS7及其以下、安卓系統都是顯示0px。

(2)使用border-image(但要注意這個屬性的兼容性):不推薦

//第一種寫法 使用媒體查詢
@media screen and (-webkit-min-device-pixel-ratio: 2){ 
    .border{ 
        border: 1px solid transparent;
        border-image: url(border.gif) 2 repeat;
    }
}
//第二種寫法 直接用類名
.border {
    border-width: 1px 0px;
    -webkit-border-image: url(border.png) 2 0 stretch;
    border-image: url(border.png) 2 0 stretch;
} 

(3)使用background漸變(但要注意這個屬性的兼容性)設置1px的漸變背景,50%有顏色,50%透明--->背景漸變, 漸變在透明色和邊框色中間分割

//第一種方式:媒體查詢
@media screen and (-webkit-min-device-pixel-ratio: 2)
{ .border{ background-position: left top; background-image: -webkit-gradient(linear,left bottom,left top,color-stop(0.5,transparent),color-stop(0.5,#e0e0e0),to(#e0e0e0)); } }
//缺點: 代碼量大, 而且需要針對不同邊框結構,而且這只是背景, 這樣做出來的邊框實際是在原本的border空間內部的, 如果元素背景色有變化的樣式, 邊框線也會消失;不適應圓角樣式
//第二種方式:直接類名
.border
{ background: linear-gradient(180deg, black, black 50%, transparent 50%) top left / 100% 1px no-repeat, linear-gradient(90deg, black, black 50%, transparent 50%) top right / 1px 100% no-repeat, linear-gradient(0, black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat, linear-gradient(-90deg, black, black 50%, transparent 50%) bottom left / 1px 100% no-repeat; }

(4)會用 :before     ,   :after 與  transform(推薦使用)

原理:把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,並 transform 的 scale 縮小一半,原先的元素相對定位,新做的 border 絕對定位。

//第一種方法
//構建1個偽元素, 將它的長寬放大到2倍, 邊框寬度設置為1px, 再以transform縮放到50%
.radius-border
{ position: relative; } @media screen and (-webkit-min-device-pixel-ratio: 2){ .radius-border:before{ content: ""; pointer-events: none; /* 防止點擊觸發 */ box-sizing: border-box; position: absolute; width: 200%; height: 200%; left: 0; top: 0; border-radius: 8px; border:1px solid #999; -webkit-transform(scale(0.5)); -webkit-transform-origin: 0 0; transform(scale(0.5)); transform-origin: 0 0; } }

//需要注意<input type="button">是沒有:before, :after偽元素的

//優點: 其實不止是圓角, 其他的邊框也可以這樣做出來

//缺點: 代碼量也很大, 占據了偽元素, 容易引起沖突

//第二種方式
//單條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; 
}
//四條border樣式設置:
.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('div').className = 'scale-1px';
}
//優點:所有場景都能滿足 支持圓角
//缺點:對於已經使用偽類的元素,可能需要多層嵌套

(5)使用flexible.js(https://github.com/amfe/lib-flexible

   原理:viewport寬度設置為實際的設備物理寬度,

(6)使用CSS3 box-shadow

.shadow {
        -webkit-box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);
    box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);
}
//不好用,不推薦

(7)viewport結合rem

//devicePixelRatio=2設置meta
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
//devicePixelRatio=3設置meta
<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">

參考文獻:

https://www.cnblogs.com/lunarorbitx/p/5287309.html

https://blog.csdn.net/xuexizhe88/article/details/80566552

本文為自己知識點搜索整理,若有侵權麻煩聯系我,刪除本文章。謝謝(* ̄︶ ̄)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

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



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