viewport
在移動設(shè)備上進(jìn)行網(wǎng)頁的重構(gòu)或開發(fā),首先得搞明白的就是移動設(shè)備上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有關(guān)的meta標(biāo)簽的使用,才能更好地讓我們的網(wǎng)頁適配或響應(yīng)各種不同分辨率的移動設(shè)備。
一、viewport的概念
移動設(shè)備上的viewport就是設(shè)備的屏幕上能用來顯示我們的網(wǎng)頁的那一塊區(qū)域,再具體一點(diǎn),就是瀏覽器上(也可能是一個app中的webview)用來顯示網(wǎng)頁的那部分區(qū)域,但是viewport的大小不局限于可視區(qū)域,默認(rèn)情況下,一般來講,移動設(shè)備上的viewport都是要大于瀏覽器可視區(qū)域的,這是因為考慮到移動設(shè)備的分辨率相對于桌面電腦來說都比較小,所以為了能在移動設(shè)備上正常顯示那些傳統(tǒng)的為桌面瀏覽器設(shè)計的網(wǎng)站,移動設(shè)備上的瀏覽器都會把自己默認(rèn)的viewport設(shè)為980px或1024px(也可能是其它值,這個是由設(shè)備自己決定的),但帶來的后果就是瀏覽器會出現(xiàn)橫向滾動條,因為瀏覽器可視區(qū)域的寬度是比這個默認(rèn)的viewport的寬度要小的。下圖列出了一些設(shè)備上瀏覽器的默認(rèn)viewport的寬度。
二、css中的1px并不等于設(shè)備的1px
在css中我們一般使用px作為單位,在桌面瀏覽器中css的1個像素往往都是對應(yīng)著電腦屏幕的1個物理像素,這可能會造成我們的一個錯覺,那就是css中的像素就是設(shè)備的物理像素。但實際情況卻并非如此,css中的像素只是一個抽象的單位,在不同的設(shè)備或不同的環(huán)境中,css中的1px所代表的設(shè)備物理像素是不同的。
??在為桌面瀏覽器設(shè)計的網(wǎng)頁中,我們無需對這個津津計較,但在移動設(shè)備上,必須弄明白這點(diǎn)。
??在早先的移動設(shè)備中,屏幕像素密度都比較低,如iphone3,它的分辨率為320x480,在iphone3上,一個css像素確實是等于一個屏幕物理像素的。后來隨著技術(shù)的發(fā)展,移動設(shè)備的屏幕像素密度越來越高,從iphone4開始,蘋果公司便推出了所謂的Retina屏,分辨率提高了一倍,變成640x960,但屏幕尺寸卻沒變化,這就意味著同樣大小的屏幕上,像素卻多了一倍,這時,一個css像素是等于兩個物理像素的。其他品牌的移動設(shè)備也是這個道理。例如安卓設(shè)備根據(jù)屏幕像素密度可分為ldpi、mdpi、hdpi、xhdpi等不同的等級,分辨率也是五花八門,安卓設(shè)備上的一個css像素相當(dāng)于多少個屏幕物理像素,也因設(shè)備的不同而不同,沒有一個定論。
??還有一個因素也會引起css中px的變化,那就是用戶縮放。例如,當(dāng)用戶把頁面放大一倍,那么css中1px所代表的物理像素也會增加一倍;反之把頁面縮小一倍,css中1px所代表的物理像素也會減少一倍。關(guān)于這點(diǎn),在文章后面的部分還會講到。
??在移動端瀏覽器中以及某些桌面瀏覽器中,window對象有一個devicePixelRatio屬性,它的官方的定義為:設(shè)備物理像素和設(shè)備獨(dú)立像素的比例,也就是 devicePixelRatio = 物理像素 / 獨(dú)立像素。css中的px就可以看做是設(shè)備的獨(dú)立像素,所以通過devicePixelRatio,我們可以知道該設(shè)備上一個css像素代表多少個物理像素。例如,在Retina屏的iphone上,devicePixelRatio的值為2,也就是說1個css像素相當(dāng)于2個物理像素。但是要注意的是,devicePixelRatio在不同的瀏覽器中還存在些許的兼容性問題,所以我們現(xiàn)在還并不能完全信賴這個東西,具體的情況可以看下這篇文章。
三、PPK的關(guān)于三個viewport的理論
ppk大神對于移動設(shè)備上的viewport有著非常多的研究(第一篇,第二篇,第三篇),有興趣的可以去看一下,本文中有很多數(shù)據(jù)和觀點(diǎn)也是出自那里。ppk認(rèn)為,移動設(shè)備上有三個viewport。
??首先,移動設(shè)備上的瀏覽器認(rèn)為自己必須能讓所有的網(wǎng)站都正常顯示,即使是那些不是為移動設(shè)備設(shè)計的網(wǎng)站。但如果以瀏覽器的可視區(qū)域作為viewport的話,因為移動設(shè)備的屏幕都不是很寬,所以那些為桌面瀏覽器設(shè)計的網(wǎng)站放到移動設(shè)備上顯示時,必然會因為移動設(shè)備的viewport太窄,而擠作一團(tuán),甚至布局什么的都會亂掉。也許有人會問,現(xiàn)在不是有很多手機(jī)分辨率都非常大嗎,比如768x1024,或者1080x1920這樣,那這樣的手機(jī)用來顯示為桌面瀏覽器設(shè)計的網(wǎng)站是沒問題的吧?
??前面我們已經(jīng)說了,css中的1px并不是代表屏幕上的1px,你分辨率越大,css中1px代表的物理像素就會越多,devicePixelRatio的值也越大,這很好理解,因為你分辨率增大了,但屏幕尺寸并沒有變大多少,必須讓css中的1px代表更多的物理像素,才能讓1px的東西在屏幕上的大小與那些低分辨率的設(shè)備差不多,不然就會因為太小而看不清。所以在1080x1920這樣的設(shè)備上,在默認(rèn)情況下,也許你只要把一個div的寬度設(shè)為300多px(視devicePixelRatio的值而定),就是滿屏的寬度了?;氐秸}上來,如果把移動設(shè)備上瀏覽器的可視區(qū)域設(shè)為viewport的話,某些網(wǎng)站就會因為viewport太窄而顯示錯亂,所以這些瀏覽器就決定默認(rèn)情況下把viewport設(shè)為一個較寬的值,比如980px,這樣的話即使是那些為桌面設(shè)計的網(wǎng)站也能在移動瀏覽器上正常顯示了。ppk把這個瀏覽器默認(rèn)的viewport叫做 layout viewport。這個layout viewport的寬度可以通過 document.documentElement.clientWidth
來獲取。
??然而,layout viewport 的寬度是大于瀏覽器可視區(qū)域的寬度的,所以我們還需要一個viewport來代表 瀏覽器可視區(qū)域的大小,ppk把這個viewport叫做 visual viewport。visual viewport的寬度可以通過window.innerWidth 來獲取,但在Android 2, Oprea mini 和 UC 8中無法正確獲取。
現(xiàn)在我們已經(jīng)有兩個viewport了:layout viewport 和 visual viewport。但瀏覽器覺得還不夠,因為現(xiàn)在越來越多的網(wǎng)站都會為移動設(shè)備進(jìn)行單獨(dú)的設(shè)計,所以必須還要有一個能完美適配移動設(shè)備的viewport。所謂的完美適配指的是,首先不需要用戶縮放和橫向滾動條就能正常的查看網(wǎng)站的所有內(nèi)容;第二,顯示的文字的大小是合適,比如一段14px大小的文字,不會因為在一個高密度像素的屏幕里顯示得太小而無法看清,理想的情況是這段14px的文字無論是在何種密度屏幕,何種分辨率下,顯示出來的大小都是差不多的。當(dāng)然,不只是文字,其他元素像圖片什么的也是這個道理。ppk把這個viewport叫做 ideal viewport,也就是第三個viewport——移動設(shè)備的理想viewport。
ideal viewport并沒有一個固定的尺寸,不同的設(shè)備擁有有不同的ideal viewport。所有的iphone的ideal viewport寬度都是320px,無論它的屏幕寬度是320還是640,也就是說,在iphone中,css中的320px就代表iphone屏幕的寬度。
但是安卓設(shè)備就比較復(fù)雜了,有320px的,有360px的,有384px的等等,關(guān)于不同的設(shè)備ideal viewport的寬度都為多少,可以到http://viewportsizes.com去查看一下,里面收集了眾多設(shè)備的理想寬度。
再總結(jié)一下:ppk把移動設(shè)備上的viewport分為layout viewport 、 visual viewport 和 ideal viewport 三類,其中的ideal viewport是最適合移動設(shè)備的viewport,ideal viewport的寬度等于移動設(shè)備的屏幕寬度,只要在css中把某一元素的寬度設(shè)為ideal viewport的寬度(單位用px),那么這個元素的寬度就是設(shè)備屏幕的寬度了,也就是寬度為100%的效果。ideal viewport 的意義在于,無論在何種分辨率的屏幕下,那些針對ideal viewport 而設(shè)計的網(wǎng)站,不需要用戶手動縮放,也不需要出現(xiàn)橫向滾動條,都可以完美的呈現(xiàn)給用戶。