Viewport 等比適配始末

小蟲巨蟹發表於2017-06-06

viewport的大小決定了,css中的設定多少畫素能剛好佔滿螢幕。例如,viewport=320,那麼設定div的寬度為320px,則div剛好能佔滿螢幕

移動裝置中1px不等於1個物理畫素

現如今,移動裝置多已經採用高倍屏,畫素解析度(物理解析度)要比邏輯解析度高,下表為iphone解析度資料

型號 畫素解析度 邏輯解析度 倍率
iphone5 640*1136 320*568 2
iphone6 750*1334 375*667 2
iphone6 plus 1242*2208 414*736 3

可以使用如下程式碼來讓viewport寬度等於邏輯解析度寬度(width=device-width)

<meta id="viewport" name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1; user-scalable=no;">複製程式碼

這個時候1px是不等於一個物理畫素的,而是等於倍率個物理畫素,如果我們在改變viewport的值,可以讓css中的1px代表的物理畫素有更多的可能

利用meta標籤對viewport進行控制

<meta id="viewport" name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1; user-scalable=no;">複製程式碼
屬性名 說明
width 設定viewport的寬度,為一個正整數,或字串"width-device"
initial-scale 設定頁面的初始縮放值,為一個數字,可以帶小數
minimum-scale 允許使用者的最小縮放值,為一個數字,可以帶小數
maximum-scale 允許使用者的最大縮放值,為一個數字,可以帶小數
height 設定viewport的高度,這個屬性對我們並不重要,很少使用
user-scalable 是否允許使用者進行縮放,值為"no"或"yes", no 代表不允許,yes代表允許

width和scale都可以用來設定viewport的值

viewport = width;
viewport = idea viewport /scale;複製程式碼

在網上搜尋到一種說法:

當同時設定了width和scale的時候,viewport的取值等於上面兩個等式計算之後得到的值大的那一個,我們常常會看到width和initial-scale同時設定的情況,那完全是為了相容各個瀏覽器

然而,嘗試之後,發現那個說法並不是很準確。如果只設定width不設定scale,在width的值大於裝置邏輯解析度的時候,內容沒有如願的充滿整個裝置,而是出現橫向滾動條(即沒有主動縮放),有點打破開篇總結的結論的意思,那真的是非常令人沮喪的。所以說:

同時設定width和scale,讓它們通過公式計算得到的viewport的值一樣,是最為安全的,也不會讓人產生疑惑

用viewport來解釋兩個靈異現象

  • 同樣的裝置,同樣是設定了border = 1px,為什麼別人的網頁上的線看起來比我的細? 現在很好解釋了,通過設定viewport,可以改變css中的1px用多少物理畫素來渲染,設定了不同的viewport,當然1px的線條看起來粗細不一致。(處女座的設計,還真有可能會為了你這1px的線條看起來太粗而找你麻煩)
  • 為什麼同樣是1px的線,在同一個裝置的同一個網頁中,不同位置看到的粗細不一致?如下圖所示,倘若在css中的1px=1.5個物理畫素,那麼在頁面中的不同位置,1px的線跨越的物理畫素有可能是兩個,也有可能是三個,用3個物理畫素表示的線肯定是要比用兩個物理畫素表示的線要寬的(雖然差異不明顯)。解決方案:設定viewport=裝置的物理解析度,讓1px=一個物理畫素

Viewport 等比適配始末
viewport.png

使用viewport來實現等比適配

倘若我們要做到把設計圖根據裝置的寬度等比縮放,整個裝到裝置中。這種適配方案對開發來說是最為友好的,拿到設計圖即可,不需要跟設計有過多的溝通,設計也不需要出多套圖,降低了成本。

把設計圖想象成一張300X300的圖片,分別按照寬度等比的裝到150X300、300X300,600X300的裝置中,那麼圖片的大小將分別變成150X150(沒裝滿容器,可能要增加點純色背景),300X300(剛好),600X600(比容器高了,得出現滾動條了)

倘若設計圖是640*1136,為了在設計圖上量到多少樣式中就能寫多少,我們有如下程式碼

    var clientWidth = document.documentElement.clientWidth,
    viewport = document.querySelector('meta[name="viewport"]');
    viewportScale = clientWidth / 640;
    viewportWidth = 640;
    viewport.setAttribute('content', 'width=' + viewportWidth + ', initial-scale=' + viewportScale + ', maximum-scale=' + viewportScale + ', user-scalable=0');
    }複製程式碼

當然問題也比較明顯:

  • 上面提到的兩個靈異現象,畫不了細線和1px的線在不同位置粗細不一致,都會存在。進化的方案,將viewport設定為物理解析度,同時為了在設計圖上量到多少樣式寫多少,可能需要在打包指令碼上做一些預處理(無論是百分比還是rem的方式)

  • 生硬的按照設計圖進行等比適配,字型的大小等看起來並不是很舒適。因為css中的1px應該代表多少個物理畫素,硬體廠商肯定有過細緻的考慮的,而我們現在修改了這個數值。成本高一點的方案:文字流式、控制元件彈性、圖片等比縮放,需要的時候,設計出多套圖,需要開發跟設計有足夠的溝通,media query也要廣泛使用

  • 在不同寬高比的裝置上,顯示效果不盡如人意。頁面底部的一個按鈕,在高屏(指的是相對於寬來說比例高)中顯示靠上;在矮屏(指相對於寬來說比例矮)中顯示靠下,甚至需要滾動一下螢幕才能看見,這個使用者體驗非常不好,更別說極端情況下不允許出現縱向滾動條了。在這種情況下可能要使用一下media query

期待您的關注~~

相關文章