移動web開發之視口viewport

小火柴的藍色理想發表於2016-05-22

前面的話

  在CSS標準文件中,視口viewport被稱為初始包含塊。這個初始包含塊是所有CSS百分比寬度推算的根源,它給CSS佈局限制了一個最大寬度。在桌面上,視口的寬度和瀏覽器視窗的寬度一致。而在移動端,視口分為佈局視口(layout viewport)、視覺視口(visual viewport)和理想視口(ideal viewport)

 

佈局視口

  移動端裝置的問題是,如果使視口的寬度和瀏覽器視窗寬度一樣會導致很醜陋的結果。移動端瀏覽器通常的寬度是240到640畫素,且大多數設計給桌面的網站的寬度至少是800px。因此網站內容在手機上看起來會非常窄

  //下圖是新浪網在手機端的顯示狀態,如果不進行縮放操作的話,文字幾乎是無法看清的

  在手機上,視口與移動端瀏覽器螢幕寬度不再相關聯,而是完全獨立的。我們稱它為佈局視口——CSS佈局會根據它來計算,並被它約束

  為了容納為桌面瀏覽器設計的網站,移動裝置預設的佈局視口寬度遠大於螢幕的寬度,設定為980px或1024px(也可能是其它值,這個是由裝置自己決定的),但帶來的後果就是瀏覽器會出現橫向滾動條,因為瀏覽器可視區域的寬度是比這個預設的viewport的寬度要小的。下圖列出了一些裝置上瀏覽器的預設viewport的寬度

  document.documentElement.clientWidth/Height返回的是佈局視口的尺寸

視覺視口

  雖然獨立佈局視口的創造很大程度地幫助了桌面網站到手機上的轉移,但我們不能完全無視移動端裝置的螢幕尺寸。一些CSS宣告與使用者見到的東西有關,而與CSS的初始包含塊無關。並且,有時候知道使用者看到了網站的哪些部分對web開發者會有幫助

  視覺視口是使用者正在看到的網站的區域,對於的javascript屬性是window.innerWidth/Height

  [注意]安卓webkit2和代理瀏覽器存在相容問題

  縮放會影響視覺視口的大小。當縮放程度是100%時,視覺視口與裝置螢幕一樣寬。放大使視覺視口變得更小,因為螢幕上顯示的CSS畫素更小了,而縮小會讓視覺視口更大,因為螢幕上的CSS畫素更多了。因此縮放程度和視覺視口的大小是逆相關的:放得越大,視覺視口越小 

  以iphone5為例,瀏覽器佈局視口的寬度預設是1024px,螢幕寬度只有640個裝置畫素,DPR為2,所以CSS畫素是320px。現在使用者從100%放大到200%,CSS畫素被放大,直到螢幕上只有160個CSS畫素。但是,佈局視口仍然保持在1024px,所以頁面中的元素並沒有改變大小。

  [注意]當使用者縮放時,只有視覺視口的尺寸會發生改變,佈局視口不會改變。移動端的縮放不會導致CSS佈局被重新計算。由於在手機上會經常發生縮放,並且手機的處理器工作得很慢,電池消耗地很快,因此不重新進行佈局對效能來說有很大的好處

  //以下程式碼表示3秒後,頁面縮放從100%到200%

<script>
test.innerHTML = '螢幕寬度:' + screen.width + '<br>視覺視口:' + window.innerWidth;
setTimeout(function(){
    var meta = document.getElementsByTagName('meta')[1];
    meta.setAttribute('content','initial-scale=2');
    test.innerHTML = '螢幕寬度:' + screen.width + '<br>視覺視口:' + window.innerWidth;
},3000);
</script>

理想視口

  預設情況下,一個手機或平板瀏覽器的佈局寬度是980或1024畫素。雖然這能讓桌面網站不被壓扁,但是這並不理想,尤其對於手機使用者,因為在狹窄的螢幕上更適合一個狹窄的網站

  換句話說,佈局視口的預設寬度並不是一個理想的寬度。這就是為什麼蘋果和其他效仿蘋果的瀏覽器廠商,會引進理想視口。它是對裝置來說,最理想的佈局視口尺寸。顯示在理想視口中的網站擁有最理想的瀏覽和閱讀的寬度,使用者剛進入頁面時也不再需要縮放

  只有當網站是為手機準備的時候才應該使用理想視口。只有主動地往頁面裡新增meta視口標籤時理想視口才會生效。如果沒有meta視口標籤宣告,那麼佈局視口將會維持它的預設寬度,理想視口只有當顯式地使用它的時候才會產生影響

//這一行程式碼告訴瀏覽器,佈局視口的寬度應該與理想視口的寬度一致
<meta name="device" content="width=device-width">

  定義理想視口是瀏覽器的工作,而不是裝置或作業系統的工作。因此,同一裝置上的不同瀏覽器擁有不同的理想視口。例如,三星galaxy pocket上的安卓webkit的理想視口是320*427px,而opera mobile12的則是240*320px。但是,瀏覽器的理想視口的大小也取決於它所處的裝置。三星galaxy s4上的chrome的理想視口是360*640px,但是在nexus7上,則是601*962px。原因很明顯:Nexus7是一個平板,它擁有更寬的螢幕,因此理想視口也應該更寬

  screen.width/height返回是理想視口的尺寸

  [注意]當裝置方向改變時,iphone中理想視口screen.width/height的值並不會改變,但安卓裝置會改變。而佈局視口document.documentElement.clientWidth和視覺視口window.innerWidth的值,蘋果和安卓都會改變

meta視口

  meta視口標籤存在的主要目的是讓佈局視口的尺寸和理想視口的尺寸匹配。它由apple發明,其他手機和平板複製了它的大部分內容。桌面瀏覽器不支援,也不需要它,因為它們沒有理想視口的概念。IE是一個例外:在手機上它支援meta視口標籤,但最好使用@-ms-viewport

  meta視口標籤應該被放在HTML文件的<head>中,並且按以下格式書寫:

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

  每一個名/值對都是一個給瀏覽器發號命令的指令。它們被逗號分隔,共有6個

  1、width:設定佈局視口的寬度為特定的值
  2、initial-scale:設定頁面的初始縮放程度和佈局視口的寬度
  3、minimum-scale:設定了最小縮放程度(使用者可縮小的程度)
  4、maximum-scale:設定了最大縮放程度(使用者可放大的程度)
  5、user-scalable:是否阻止使用者進行縮放
  6、height:設定佈局視口的高度(未被實現)

width

  【0】不設定寬度

  例如,iPhone4S如果不設定viewport,他就會預設是980px,就像把螢幕分成980份。如果設定一個元素為100px*100px,看起來就是螢幕的100/980

  【1】把佈局視口的尺寸設為一個理想的值

<meta name="viewport" content="width=device-width">

  假如,iPhone4S如果設定viewport width=device-width,他就會是320px,就像把螢幕分成320份。如果設定一個元素為100px*100px,看起來就是螢幕的100/320 

  【2】把佈局視口的尺寸設為固定寬度

<meta name="viewport" content="width=400">

  瀏覽器支援的最大值是10000個畫素,最小值約為理想視口的20%,安卓webkit不允許任何小於佈局視口的寬度。如果你指定了一個這樣的值,它會自動轉換為預設佈局視口,通常是980px。IE10不允許任何超出480px的值,超出的話會自動轉換為佈局視口的預設寬度1024px

initial-scale

  initial-scale指令設定了頁面的初始縮放程度。1代表100%,2代表200%。縮放程度是根據理想視口來計算的

當前縮放值 = 理想視口寬度  / 視覺視口寬度

  [注意]安卓自帶的webkit瀏覽器只有在 initial-scale = 1 以及沒有設定width屬性時才表現正常

  縮放程度與視覺視口的寬度是逆相關的,越高的縮放程度意味著視覺視口越小。所以initial-scale=1時視覺視口尺寸和理想視口尺寸是一樣的。initial-scale=2會放大到200%,因此視覺視口的高寬是理想視口的一半

【預設值】

  安卓裝置上的initial-scale並沒有預設值,而在iphone和ipad上,無論viewport設定的寬度是多少,如果沒有指定預設的縮放值,則iphone和ipad會自動計算這個縮放值,以達到當前頁面不會出現橫向滾動條(或者說viewport的寬度就是螢幕的寬度)的目的 

【1】width=device-width,initial-scale=1

  IE10中當initial-scale為1時,它在橫屏模式下寬度保持著320px,但width=device-width時它會從320px變為480px

  所以為了在所有瀏覽器上解決這個問題,需要使用

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

【2】width=400,initial-scale=1

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

  把佈局視口的寬度設為400px,然後再把它設為理想視口的寬度。結果瀏覽器選擇了每個方向最大的尺寸。因此早期的iphone手機在豎屏模式下的佈局視口寬度是400px(320px和400px中較大的值),在橫屏模式下是480px(480px和400px較大的值)

  因此,可以給佈局視口設定一個最小寬度,並在裝置和方向上有需求時允許瀏覽器將佈局視口設得更寬

minimum-scale和maximum-scale

  沒有這些指令的時候,瀏覽器允許使用者的縮放級別達到5(20%-500%);有這些指令的時候,範圍可擴大到10(10%到1000%)。更高的縮放程度不被支援,因此設定maximum-scale=20和設定maximum-scale=10的效果是一樣的。安卓webkit不支援minimum-scale。同樣,它的縮放範圍是4(25%-400%),並且不支援改變這個範圍

user-scalable

  user-scalable=no表示禁止縮放

【改變meta視口標籤】

  在大多數瀏覽器中,可以改變meta視口標籤,假設meta視口是文件中的第一個meta標籤

var meta = document.getElementsByTagName('meta')[0];
meta.setAttribute('content','width=400');

  我們無法通過移除meta標籤來使佈局視口變回它預設的寬度。但可以把它設為一個固定的值。例如,如果想提供"切換到桌面佈局"的功能,可以把寬度設為980px或1024px

【常用meta視口標籤】

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

  該meta標籤的作用是讓當前viewport的寬度等於裝置的寬度,同時不允許使用者手動縮放

【IOS9+專用屬性】

"shrink-to-fit=no"

  使用Viewport元標記"width=device-width"會導致頁面縮小以適應溢位視口邊界的內容。可以通過新增"shrink-to-fit=no"到meta標籤來覆蓋此行為,增加的值將阻止頁面縮放以適應視口

 

總結

  在桌面瀏覽器中,瀏覽器視窗就是約束CSS佈局的視口。而在手機端,佈局視口會限制CSS佈局;視覺視口表示瀏覽器的可視區域,決定使用者看到什麼;理想視口是對於特定裝置的特定瀏覽器的佈局視口的一個理想尺寸

 

相關文章