1. 程式人生 > >移動端1px誤差的原因以及解決方案

移動端1px誤差的原因以及解決方案

移動端1px問題在面試和工作中會經常遇到,系統地理解它是一個優秀前端的必修課!

為什麼移動端css裡面寫了1px, 實際看起來比1px粗. 其實原因很好理解:這2個’px’的含義是不一樣的. 移動端html的header總會有一句

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

這句話定義了本頁面的viewport的寬度為裝置寬度,初始縮放值和最大縮放值都為1,並禁止了使用者縮放。
手機存在一個能完美適配的理想viewport, 解析度相差很大的手機的理想viewport的寬度可能是一樣的, 這樣做的目的是為了保證同樣的css在不同螢幕下的顯示效果是一致的, viewport的好處就在於一套css可以適配多個機型

在window物件中有一個devicePixelRatio屬性,他可以反應css中的畫素與裝置的畫素比。然而1px在不同的移動裝置上都等於這個移動裝置的1px,這是因為不同的移動裝置有不同的畫素密度。有關這個屬性,它的官方的定義為:裝置物理畫素和裝置獨立畫素的比例,也就是

devicePixelRatio = 物理畫素 / 獨立畫素

1px變粗的原因: viewport的設定和螢幕物理解析度是按比例而不是相同的. 移動端window物件有個devicePixelRatio屬性, 它表示裝置物理畫素和css畫素的比例, 在retina屏的iphone手機上, 這個值為2或3, css裡寫的1px長度對映到物理畫素上就有2px或3px那麼長。

解決方案
1.rem解決:

////根據螢幕大小及dpi調整縮放和大小  
(function () {
        var scale = 1.0;
        var ratio = 1;
        if (window.devicePixelRatio >= 2) {
            scale *= 0.5;
            ratio *= 2;
        }
        var text = '<meta name="viewport" content="initial-scale=' + scale + ', maximum-scale='
+ scale + ',' + ' minimum-scale=' + scale + ', width=device-width,' + ' user-scalable=no" /> '; document.write(text); document.documentElement.style.fontSize = 50 * ratio + "px"; })();

2.flexible.js
這是淘寶移動端採取的方案, github的地址:https://github.com/amfe/lib-flexible. 前面已經說過1px變粗的原因就在於一刀切的設定viewport寬度, 如果能把viewport寬度設定為實際的裝置物理寬度, css裡的1px不就等於實際1px長了麼. flexible.js就是這樣乾的。

<meta name=”viewport”>裡面的scale值指的是對ideal viewport的縮放, flexible.js檢測到IOS機型, 會算出scale = 1/devicePixelRatio, 然後設定viewport

metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

3.偽類+transform實現
對於解決1px邊框問題,我個人覺得最完美的解決辦法還是偽類+transform比較好。
原理:是把原先元素的 border 去掉,然後利用 :before 或者 :after 重做 border ,並 transform 的 scale 縮小一半,原先的元素相對定位,新做的 border 絕對定位。

<!DOCTYPE html> 
<html> 
 <head> 
 <meta charset="UTF-8"> 
 <title>test</title> 
 </head> 
 <body> 
<div class="box-shadow-1px scale">box-shadow-1px</div>
<style>
.box-shadow-1px {
    height: 200px;
    width: 200px;
    text-align: center;
}
.scale{
  position: relative;
  margin-bottom: 20px;
  border:none;
}
.scale: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;
}
</style>
 <script> 

console.log(typeof ('a'+1))



 </script> 
 </body> 
</html>

這裡寫圖片描述