Meta viewport (視口元信息標籤)

    前幾天在研究移動版開發時,意外查閱到了PPK大神的關於viewport(視口)的三篇研究文檔,但其中一篇無奈全是英文,只好硬着頭皮看下去,並順便試着翻譯一下,以備日後回顧。
    本人水平有限,如翻譯錯誤,歡迎指正

原文地址:http://www.quirksmode.org/mobile/metaviewport/#t10

另外兩篇文檔的地址:
原文:http://www.quirksmode.org/mobile/viewports.html
譯文:http://weizhifeng.net/viewports.html

原文:http://www.quirksmode.org/mobile/viewports2.html
譯文:http://weizhifeng.net/viewports2.html

讀前須知:PPK寫這篇文章的時候,IPhone還沒有生產出4S之後的產品。所以,這篇文章中提到的IPhone,都是指IPhone4S及之前的手機。

序言

      本文涵蓋了我關於meta標籤中的viewport屬性的所有規則(directives)的研究
      @viewport的概念不在本文討論範圍之內,我將在研究清楚它的工作原理後再作說明

視口元信息標籤

      viewport元信息標籤向瀏覽器指明瞭viewport大小和頁面縮放比例的信息。而且,它允許web開發人員設置layout viewport的寬度,這個寬度可以是相對於CSS聲明(如width:20%)的計算結果。

viewport元信息標籤的語法如下:

<meta name="viewport" content="name=value,name=value">

規則

      每一個名/值對就是一個規則(這個說法是我創建的),共有6個規則:

width:用於設置layout viewport(佈局視口)的寬度

initial-scale:設置頁面的初始縮放比 layout viewport(佈局視口)的寬度

minimum-scale:設置頁面最小縮放比例,即用戶能將頁面縮小多少

maximum-scale:設置頁面最大縮放比例,即用戶能將頁面放大多少

height:應該是用於設置layout viewport(佈局視口)的高度,但該屬性無效

user-scalable:當設置爲no時,可禁止用戶縮放頁面。但請不要這樣去做。

device-width值

      width規則下有一個特殊的值device-width,通過設置width=device-width可以將layout viewport(佈局視口)的寬度等於 ideal viewport(理想視口)的寬。

      理論上,有一個類似的device-height的值,但它不起作用。

三種viewport

      幾年前,我在一篇文章中說過“手機瀏覽器有2個viewport:visual viewport(可視視口)和layout viewport(佈局視口)”。如果大家覺得有必要,請再閱讀一下這篇文檔:

原文地址

以下內容將在2個viewport知識的基礎上繼續討論。

理想視口 ideal viewport

      事實證明,還有第三個viewport,我稱之爲理想視口( ideal viewport)。它給出了移動設備上一個網頁的理想大小。因此,理想視口( ideal viewport)的尺寸在每一個設備上都是不同的。

點擊PPK的常見設備的理想視口和最小布局視口一覽表可以查看一些設備的理想視口的尺寸

      在一些老舊或者低端的非Retina屏的移動設備上,理想視口( ideal viewport)的大小等於其物理像素,但這並非一定正確。擁有較高的物理像素密度的一些新設備也可能保留了老版本手機的理想視口( ideal viewport)大小,因爲這個尺寸很適合這些設備。

      包括4S在內的早期IPhone手機,不論它們是否有Retina屏,它們的理想視口( ideal viewport)都是320x480。這是因爲320x480是這些手機設備上網頁的理想尺寸。

關於理想視口( ideal viewport),有如下2個重要的說明
    1、使用 width=device-width 和initial-scale=1,可以將 layout viewport的值設置爲 ideal viewport的大小。
    2、所有的縮放規則都是相對於 ideal viewport而言的,而與layout viewport多寬無關。因此maximum-scale=3的含義就是頁面最多放大到 ideal viewport的3倍。

獲取 ideal viewport 的尺寸

      如果幸運的話,偶爾讀出來的 ideal viewport的尺寸是有用的。

在一個頁面上使用下面的的meta標籤:

<meta name="viewport" content="width=device-width,initial-scale=1">

讀取出document.documentElement.clientWidth和 document.documentElement.clientHeight的值就是ideal viewport的尺寸。

      如果沒法讀出 ideal viewport的尺寸不是你的選項(即必須要讀出 ideal viewport的尺寸),通過screen.width/height的值來獲取ideal viewport的尺寸也可以,但這種方式只有在黑莓(BlackBerry)設備上纔有效,在其他瀏覽器上都是些無用值。

Open question:通過screen.width/height應該獲取到ideal viewport的尺寸嗎?
贊成:這個屬性最終應該包含ideal viewport尺寸的有用信息
反對:ideal viewport的大小並不一定等同於設備的物理像素

ideal viewport的兼容性

現在用表格表示一下上述內容的兼容性

這裏寫圖片描述

上表中的英語內容的譯文如下:

Test Devices
ideal viewport 尺寸 這些值沒有對錯,它們都由設備本身決定,這些值都是正常的
是否通過設置width = device-width,layout viewport的寬等於ideal viewport Safari上橫屏模式和豎屏模式的寬都是豎屏模式的寬(portrait width)(即320 or 768)
是否通過設置initial-scale=1,layout viewport的寬等於ideal viewport IE10上橫屏模式和豎屏模式的寬都是豎屏模式的寬(portrait width)(即320)
是否通過screen.width/height可以獲取理想視口的尺寸 Safari總是給出豎屏的理想視口的尺寸;
Chrome和Opera給出的是有效高度(屏幕高度減去工具欄等),但寬度是正確的;
Android和IE給出的是屏幕的物理像素;

Layout viewport 的寬度

      在渲染網頁之前,瀏覽器得知道layout viewport的寬度。這個視口的寬度是根據CSS聲明的寬度(例如width:20%)計算得出的。

      當瀏覽器沒有獲得更詳細的設置信息時,它們會自主決定layout viewport的寬度。在測試的8個瀏覽器中的6個上,這個值是980px,在BlackBerry 和IE10上是1024px。取哪個值由瀏覽器廠商決定,沒什麼對錯之說。

      我們已經知道,當在viewport元信息標籤中設置width=400或者其他數值時,layout viewport的寬度就等於這個數值。

      但是,在Android瀏覽器的webkit內核和IE上,layout視口的最小值是320px。當這個視口小於320px時,它們會恢復到ideal viewport的寬度。

      因此,當layout viewport的尺寸等於ideal viewport時,會出現一種很複雜的情況(這種情況發生在當設置width=device-width 或者initial-scale=1時):在Safari和IE10上會有一個bug,因爲它們在識別initial-scale上有兼容問題(但這只是一般規律)。

最大和最小尺寸

      layout viewport的最大寬度是10,000px,我不完全相信這個數值,因爲瀏覽器不允許頁面縮放到這個大。但儘管不相信,目前我接受這個官方數值。

      layout viewport的最小寬度大約是ideal viewport的十分之一,這也是最大的縮放程度了。layout viewport永不會變得比最小的visual viewport更小。但有一個例外情況:Android WebKit內核和IE瀏覽器的layout viewport永不會小於320px。

layout viewport的兼容性

現在用表格表示一下上述內容的兼容性
這裏寫圖片描述

上表中的英語內容的譯文如下:

Test Devices
默認layout viewport的大小 這些值沒有對錯,它們都由設備本身決定,它們都是正常的
通過設置width=10000,minimum-scale=0.01來獲取layout viewport的最大寬度 當數值超過10000時,所有瀏覽器都保持爲10000,除了android webkit內核瀏覽,它會恢復到默認的980px
通過設置width=5來獲取layout viewport的最小寬度 下面聲明的320px寬度是Android WebKit內核和IE瀏覽器採用的ideal viewport尺寸
通過設置一些正常的值:
width = 200
width=300
width=400
width=1200
瀏覽器會盡量使layout viewport的寬度和width屬性定義的值相等
a、當設置了width=200,在IPad的橫屏模式會是205px寬,這與它最小layout viewport寬是一致的
b、當小於320px時,Android WebKit內核和IE瀏覽器將會將ideal viewport的寬當作layout viewport的最小寬度

縮放

      縮放很麻煩,儘管在理論上它聽起來很簡單:決定能放大或縮小的縮放因子。
1、無法直接獲取縮放因子。事實上,我們得先獲得visual viewport的寬,它與縮放因子呈反比例關係。縮放因子越大,visual viewport的寬度越小。所以最小縮放因子決定了最大視覺視口的寬度,反之亦然。
2、事實證明,所有的縮放因子都與ideal viewport存在關係,而不論當時layout viewport的大小是多少。

      還有一個關於名稱的問題。在蘋果系統上,zoom稱爲scale,所以在viewport meta標籤中,規則就寫成:initial-scale,minimum-scale和maximum-scale。其他瀏覽器被迫遵守這條規則,以兼容特定於IPhone端的網頁。

      使用這三個規則規定了一個縮放因子。例如縮放因子爲2表示縮放到ideal viewport寬的200%。

公式

先給出公式:

visual viewport width = ideal viewport width / zoom factor
zoom factor = ideal viewport width / visual viewport width

      因此,已知ideal viewport的寬爲320px,縮放因子爲2,就可以算出visual viewport寬等於160px (=320px/2)。layout viewport的寬度在這個公式中沒有作用。

最大最小縮放因子

      瀏覽器支持的縮放因子的最小值和最大值是多少?

      首先說一個約束規定:visual viewport永不會比layout viewport更寬。所以在大多數實際情況下,最小縮放因子= ideal viewport的寬 / layout viewport的寬。
      然而在這些測試中,我用了一個荒誕的layout viewport寬度值—5000,得到如下結果:
      1、Android WebKit內核瀏覽器的最小縮放因子是0.25,最大值是4。這個值不可修改。通過640 / 0.25得到的2,560px這個值在橫屏和豎屏模式下都是正確的。
      2、IE瀏覽器的最大visual viewport寬是1024px,最大縮放因子在豎屏下是6,在橫屏下是20/3。這個值不可修改。
      3、在其他瀏覽器, 不寫任何縮放規則時,最小縮放因子大約是0.25,最大大約是5。
      4、增加這樣一條縮放規則:當layout viewport無限寬或maximum-scale無限大的情況下,最小縮放因子約是0.1,最大約10

      因此,理論上IPhone的visual viewport寬可以是介於32px(縮放因子爲10)和3200px(縮放因子爲0.1)之間的任意值。

      這些縮放規則在不同設備上有些細微差別,詳見下圖。
這裏寫圖片描述
這裏寫圖片描述

      我額外在Huawei C8813, Android 4.1.1上做了些測試。因爲它們橫屏模式下的ideal viewport寬是569。同樣,它們最小和最大縮放因子也是0.25和4。因此,上述4條規則是Android WebKit內核瀏覽器的通用規則,而不只是三星、HTC等測試手機在640px這個特定寬度下結果。同樣,最大visual viewport寬是2277px,大體上等於4 x 569。

縮放的兼容性

現在用表格表示一下上述內容的兼容性
這裏寫圖片描述
這裏寫圖片描述

上表中的英語內容的譯文如下:

initial-scale

      設置 initial-scale這條規則實際上做了如下2件事:
      1、將頁面初始縮放因子設置爲給定的值,計算出相對於ideal viewport,得到visual viewport的寬。
      2、設置layout viewport的寬等於剛剛計算出來的visual viewport的寬

      如果一個IPhone手機處於豎屏模式,設置其initital-scale=2並且沒有其他設置。那麼不要奇怪,它其實是設置了visual viewport的寬爲160px (=320px/2),這就是縮放規則的工作方式。

      而且,它同時也設置了layout viewport的寬度爲160px。因此我們現在擁有一個在最小縮放比例下160px寬的網頁。(visual viewport不能比layout viewport大,所以頁面不可能放大了)

      但是,這好像沒什麼意義。如果你問我的真實想法是什麼,我會說“完全TMD沒用”,但毫無疑問,瀏覽器就是這麼幹了。

瀏覽器bugs

      很明顯Android WebKit瀏覽器是個例外,它允許使用initial-scale設置layout viewport的寬,當且僅當其值爲1並且沒有其他寬度設置規則。即Android WebKit瀏覽器的規則中僅有initial-scale=1起作用。

      對於IE,會獲取一個錯誤的ideal viewport(320x320而不是320x480),並且會將任意值都當作成1,所以在IE上initial-scale取什麼值都無所謂。

定義寬度規則時的衝突

      由於initial-scale是設置layout viewport的寬度的,所以可以利用如下的代碼製造指令衝突:

<meta name="viewport" content="initial-scale=1,width=400">

      那麼瀏覽器得到相互衝突的指令後會發生什麼呢?讓我們再次回到IPhone 4S上看看:
      1、initial-scale=1告訴瀏覽器要將layout viewport的寬度設置爲320px(豎屏模式)和480px(橫屏模式)
      2、width=400告訴瀏覽器要將layout viewport的寬度在橫屏和豎屏模式下都設置爲400px

      瀏覽器解決這個衝突的方法是:寬度最大優先原則(橫屏或豎屏模式下均是)。

      在我們的例子中,豎屏模式下layout viewport的寬度將變爲400px(取320和400中的較大值),橫屏模式下layout viewport的寬度將變爲480px(取480和400中的較大值)。

      有什麼道理或依據嗎?沒有!但瀏覽器就這麼任性地去做了。

      在任何情況下,我們這裏說一個layout viewport的min-width的情況。如果在上面的meta標籤設置了min-width爲400px,但允許瀏覽器增加layout viewport的寬度並超過這個值,只有設備尺寸或者設備旋轉需要。

      我不清楚是否有layout viewport的min-width的實際應用,但如果你需要,就在這裏。

瀏覽器bugs

      Android WebKit內核瀏覽器不遵循這條規則。如果width等於device-width或者小於320px,Android WebKit內核瀏覽器總會採用ideal viewport的寬作爲layout viewport的寬。超過320都會遵循這個規律。

IE does not follow these rules above width=480, when it sets the layout viewport width to 1024px.

      在width=480以上,IE不遵循這些規則,如當設置了layout viweport寬爲1024px

initial-scale和 width的兼容性

這裏寫圖片描述
這裏寫圖片描述

iPhone手機上的小bug

      我在IPhone上發現一個小bug,但IPad上沒有。
      1、如果在橫屏模式下使用width和initial-scale組合,將會引起瀏覽器自動縮小。(即視覺視口小於佈局視口)
      2、並且,如果用戶在橫屏模式下放大頁面,手機就會切換到豎屏模式。
      3、豎屏模式下的最小縮放比等於橫屏模式下的最小縮放比(即viewport寬) * 豎屏/橫屏比率(So a landscape viewport width of 400 causes a portrait minimum-scale of 268)。
      4、解決方案:在豎屏模式下儘可能的縮小,這個bug就消失了。

      你可以前往這個頁面,按照以上步驟操作試試。

minimum-scale 和maximum-scale

      我只是做了一系列關於minimum-scale和maximum-scale的小測試,測試結果都很正常,除了在Android WebKit(因爲它不支持minimum-scale)和IE(因爲它製造出一系列糟糕的問題)上,所以我放棄了嘗試搞懂它們的工作原理。

      當layout viewport的寬按照上述計算,然後縮放被限制在50%和200%之間,即視覺視口可以變爲從理想視口的一倍大到兩倍小。猜猜會發生什麼?(答案如下圖)

      一個例外情況是:visual viewport永不會變得比layout viewport小。

這裏寫圖片描述

瀏覽器

[an error occurred while processing this directive]
(在處理這個規則時發生錯誤)


—————–華麗的分隔線———————

以下是本人的總結

總結

大致翻譯了PPK大牛的神作,但我讀完也還是特別凌亂,特總結一下

1、ideal viewport的尺寸在每一個設備上都不同
2、所有的縮放規則都是相對於 ideal viewport而言的,而與layout viewport無關
3、使用width=device-width和initial-scale=1兩個規則,都可以將 layout viewport的值設置爲ideal viewport的大小,但存在兼容問題:IPhone上只識別initial-scale;IE上只識別width=device-width;所以要結合起來一起使用。
4、設置了上述meta指令後, 讀取出document.documentElement.clientWidth和 document.documentElement.clientHeight的值就是ideal viewport的尺寸(黑莓上是通過screen.width/height來獲取)
5、layout viewport的寬度默認是980px或1024px
6、visual viewport width = ideal viewport width / zoom factor
7、Android WebKit內核和IE瀏覽器的layout viewport永不會小於320px。當這個視口小於320px時,它們會恢復到ideal viewport的寬度
8、layout viewport的最小寬度大約是ideal viewport的十分之一,這也是最大的縮放程度了;layout viewport的最大寬度是10,000px,IE爲1024px
9、visual viewport永不會比layout viewport寬
10、Android WebKit內核瀏覽器的最小縮放因子是0.25,最大值是4,這個值不可修改
11、IE瀏覽器的最大visual viewport寬是1024px,最大縮放因子在豎屏下是6,在橫屏下是20/3,這個值不可修改
12、在其他瀏覽器, 不寫任何縮放規則時,最小縮放因子大約是0.25,最大大約是5
13、當layout viewport無限寬或maximum-scale無限大的情況下,最小縮放因子約是0.1,最大約10
14、設置 initial-scale這條規則實際上做了如下2件事:
      a、將頁面初始縮放因子設置爲給定的值,計算出相對於ideal viewport,得到visual viewport的寬。
       b、設置layout viewport的寬等於剛剛計算出來的visual viewport的寬
15、如果在meta中同時設置了initial-scale=1和width=400,則發生寬度規則衝突的解決方案是:寬度最大優先原則
16、width:用於設置layout viewpor的寬度

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章