這篇文章是我在個人舊博客上發過的文章,最近又碰到這個問題,整理修改了一下發到這裏。css
像素單位有設備像素、邏輯像素和CSS像素3種。html
設備像素也叫物理像素。
設備像素指的是顯示器上的真實像素,每一個像素的大小是屏幕固有的屬性,屏幕出廠之後就不會改變了。
設備分辨率描述的就是這個顯示器的寬和高分別是多少個設備像素。
設備像素和設備分辨率交給操做系統來管理,瀏覽器不知道、也不須要知道設備分辨率的大小,瀏覽器只須要知道邏輯分辨率就能夠了。前端
設備獨立像素也叫邏輯像素。
設備獨立像素(dips)是操做系統爲了方便開發者而提供的一種抽象。應用程序與操做系統之間描述長度時以設備獨立像素爲單位,而後操做系統再將單位從設備獨立像素轉化爲設備像素,從而控制屏幕上真正的物理像素點。web
爲何須要在應用程序與設備像素之間定義這麼一種單位呢?爲何應用程序不該該直接使用設備像素來描述長度?
隨着顯示器製造技術愈來愈先進,屏幕像素密度愈來愈高。一樣是1920*1080顆像素,之前要放在寬大的顯示器中,如今均可以放在手機屏幕上了。本來高度爲12個設備像素的字體,如今高度爲24個設備像素才能獲得相近的大小(這也說明字變得更加清晰銳利了),若是應用程序直接使用設備像素,那麼編寫應用程序將變得很是困難:字體在一些屏幕上高度爲12個設備像素,在另外一些屏幕上卻要變爲24個設備像素。
所以操做系統定義了一個單位:設備獨立像素。操做系統保證:用設備獨立像素定義的尺寸,無論屏幕的參數如何,都能以合適的大小顯示(這也是設備獨立像素名字的由來)。操做系統是如何作到的呢?對於那些像素密度高的屏幕,將多個設備像素劃分爲一個邏輯像素。至於將多少設備像素劃分爲一個邏輯像素,這由操做系統決定。
對於上面的例子:「本來高度爲12個設備像素的字體,如今高度爲24個設備像素才能獲得相同的大小」,操做系統會將一個邏輯像素定義爲2*2個真實像素,從而設備獨立像素尺寸不須要改變,並且無論在新、舊設備上,顯示的尺寸大體相同。chrome
設備獨立像素與設備像素之間的比例是多少,顯示器廠商和操做系統廠商會經過調查研究來得出最利於觀看的比例。廣泛規律是,屏幕的像素密度越高,就須要更多的設備像素來顯示一個設備獨立像素。
經過screen.width/height
獲得的數值就是整個屏幕(不只僅是瀏覽器的區域)的寬度和高度(單位:設備獨立像素)。這個數值不隨頁面縮放、瀏覽器窗口大小而改變。segmentfault
邏輯分辨率用屏幕的寬*高來表示(單位:設備獨立像素)。瀏覽器
你能夠經過操做系統的分辨率設置來改變設備獨立像素的大小,但在前端開發的時候咱們徹底能夠將它們看成定值。(沒人會閒着無聊頻繁改變操做系統分辨率)
我屏幕的設備分辨率是1920*1200(單位:設備像素),當前的分辨率設置下邏輯分辨率是1280*800(單位:設備獨立像素)。從圖中能夠驗證,橫、縱方向的設備像素數量剛好是設備獨立像素的1.5倍。這也意味着,設備獨立像素的邊長是設備像素邊長的1.5倍。dom
window.devicePixelRatio在下文會解釋。
在CSS中使用的px
都是指css像素,好比width: 128px
。css像素的大小是很容易變化的。當咱們縮放頁面的時候,元素的css像素數量不會改變,改變的只是每一個css像素的大小。也就是說width: 128px
的元素在縮放200%之後,寬度依然是128個css像素,只不過每一個css像素的寬度和高度變爲原來的兩倍。若是本來元素寬度爲128個設備獨立像素,那麼縮放200%之後元素寬度爲256個設備獨立像素(css像素寬度始終是128)。chrome-devtools
開發者在開發的時候基本上只用考慮css像素,在這裏介紹設備像素和設備獨立像素只是爲了講述頁面縮放的原理,以及方便之後理解viewport。
縮放比例就是css像素邊長/設備獨立像素邊長。
根據縮放比例和設備獨立像素邊長,就能計算出css像素邊長。
在縮放比例爲100%的狀況下,一個css像素大小等於一個設備獨立像素。佈局
window.devicePixelRatio設備像素比。
devicePixelRatio = CSS像素邊長/設備像素邊長。好比devicePixelRatio=2,表示CSS像素的邊長是設備像素的2倍,所以在相同長度的直線上,設備像素的數量是CSS像素數量的2倍,須要4個設備像素來顯示1個CSS像素。
在桌面瀏覽器上,縮放會致使CSS像素邊長的改變,從而致使window.devicePixelRatio的改變!
可是!當移動端瀏覽器加入討論時,事情就變得複雜了一些。事實上,桌面瀏覽器與移動端瀏覽器的縮放機制是不同的!桌面瀏覽器的是page zoom,移動端瀏覽器的是pinch zoom。
根據CSS標準,計算window.devicePixelRatio時,不考慮pinch zoom對CSS像素尺寸的影響。所以,在移動端縮放不會形成window.devicePixelRatio的改變。經過chrome的遠程調試就能測試出這一點。
以上2張圖展現了我在移動端瀏覽器上縮放先後,分別獲取到的devicePixelRatio值,能夠看出它不受縮放的影響。
page zoom和pinch zoom的主要區別是,前者會形成layout viewport的尺寸(以CSS像素爲單位)改變然後者不會。
爲何要弄兩套縮放機制?這是由於, 在桌面端放大時,用戶 不但願出現橫向滾動條,所以須要將 layout viewport(網頁佈局寬度)始終保持與visual viewport(瀏覽器窗口可視寬度)相等。在縮放時,它們的 物理尺寸是不變的(好比,以釐米爲單位或者以設備像素爲單位),可是CSS像素的尺寸會隨着縮放變大,結果就是 網頁的layout/visual viewport(以CSS像素爲單位)變小了(一行只能顯示更少的字)。而 在移動端,手機的屏幕很是窄,若是使用一樣的機制,用戶一放大,網頁的layout viewport變小(好比小到只有200CSS像素),佈局就會很是噁心。所以,在移動端放大時,瀏覽器再也不干涉layout viewport,讓它隨着CSS像素一塊兒「膨脹」, layout viewport的寬度(以CSS像素爲單位)不變,可是visual viewport的寬度(以CSS像素爲單位)變小,所以會出現橫向滾動條。(你會發現,在手機上放大網頁,一行可以顯示的字的數量不變,只不過須要橫向滾動才能看完一整行)
ppk大神在 他的文章中也解釋了page zoom和pinch zoom。
另外請注意,改變操做系統分辨率會致使設備獨立像素邊長改變,從而致使CSS像素邊長改變(前面已經說過,CSS像素邊長是根據縮放比例和設備獨立像素計算出來的),從而致使window.devicePixelRatio的改變!網上不少文章不區分設備獨立像素和設備像素,那樣就沒法解釋這個現象。
個人屏幕寬度是1280個設備獨立像素。這個值能夠直接經過window.screen.width
得到,或者本身根據操做系統的縮放比例和顯示器物理像素寬度來計算。我將div寬度也設爲了1280px(css像素),當縮放爲100%的時候,DIV剛好撐滿整個屏幕,不會出現橫向滾動條。(這說明縮放比例爲100%的時候一個CSS像素徹底等於一個設備獨立像素。)
這裏有一個小坑點。 若是縱向滾動條存在的話,它會佔據一點點寬度,這時若是我還將元素寬度設爲屏幕寬度1280px,屏幕就沒法裝下整個元素,而後就會出現橫向滾動條。
在上面這個例子中由於縱向滾動條不存在,因此沒有這個問題,未來在開發的時候要注意。注意到我設置了5px的橙色邊框,爲何最終的寬度不是1280+5+5=1290呢?由於我給全部元素加上了
box-sizing: border-box
的樣式,這樣我設置的邊框寬度就會包含在width中,也就是最終加上邊框之後寬度爲1280px。
當我縮小瀏覽器窗口的時候滾動條出現了。由於div的寬度沒有改變,不管以什麼單位衡量(設備像素、設備獨立像素仍是CSS像素)。
由於縮放依然是100%,css像素邊長/設備獨立像素邊長依然是1:1。
將窗口最大化,並經過Ctrl+鼠標滾輪
將瀏覽器縮放調整爲200%,屏幕只能顯示DIV的左半部分了,這時DIV的寬度依然是1280個css像素,可是它寬度變成了2560個設備獨立像素。
如下是測試用的簡單代碼,你們能夠本身在Chrome中試試!
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <title>test</title> <style> * { padding: 0; margin: 0; box-sizing: border-box; } body { text-align: center; } #box { /* 這裏的width設置爲screen.width的值,screen.width以設備獨立像素爲單位,給出屏幕的寬度。 從而,在縮放爲100%時,#box的寬度剛好等於屏幕寬度。 */ width: 1280px; /* 限制高度防止出現縱向滾動條 */ max-height: 100vh; background: lightblue; border: 5px solid orangered; border-radius: 20px; } /* media query rule中px的單位是設備獨立像素,與縮放比例無關! 也就是說,僅僅經過縮放窗口,不可能觸發如下樣式的切換。 */ @media (max-width: 640px) { #box { background-color: aqua; } } </style> </head> <body> <div id="box">this is box<br> 1 <br> 2 <br> 3 <br> 4 <br> 5 <br> 6 <br> 7 <br> 8 <br> 9 <br> 10 <br> </div> </body> </html>
歡迎閱讀下一篇文章:initial containing block、viewport以及相關尺寸,它使用這篇文章介紹的3個概念,來解釋響應式佈局中有關的概念和屬性。