屏幕是由一個一個顯示單元組成的.
1 每個顯示單元都是物理世界真實存在的;
2 把一個顯示單元的大小稱爲一個'物理像素';
3 一般咱們所說的 '分辨率', 就是指一塊屏幕顯示單元的個數, 好比750*1334
, 表示這塊屏幕由 750*1334
個顯示單元組成javascript
像素是計算機系統裏面的單位, 一般狀況下, 咱們讓一個像素對應一個顯示單元. 因此有時候, 咱們說屏幕高 667px, 實際上就是說, 屏幕的的高有 667個顯示單元的高度之和. html
隨着技術的進步, 顯示單元能夠作的愈來愈小, 好比之前是 10mm*10mm
的一個顯示單元, 如今咱們能夠作到 5mm*5mm
一個顯示單元.
爲何追求顯示單元的小? 由於越小圖像越精細. java
可是: 顯示單元的變小, 意味着屏幕的分辨率變大。瀏覽器
這裏就牽涉到了一些事情:佈局
假設屏幕的大小不變, 可是分辨率從 A, 變成 2A (也就是顯示單元縮小了一半)
而且: 一個像素對應一個顯示單元, 這個規則始終不變code
此時, 你原來寬度爲 100px 的一個元素, 在這個 2A 屏幕上渲染出來, 你會明顯的發現:
在視覺上: 這個 100px 明顯比以前小了, 和以前的 50px 的時候同樣大小. htm
那怎麼辦啊, 這樣顯示確定是不能夠的, 因此咱們要對這個狀況作處理:ip
1 咱們規定, 大小爲 n*n 的顯示單元, 是標準的顯示單元, 標準意味着它合乎咱們長久的判斷: 100px 在物理世界大概有多大. 開發
2 咱們要知道當前屏幕的顯示單元, 和標準顯示單元之間的大小比例,好比說當前屏幕的顯示單元的大小是標準的一半仍是 三分之一. rem
經過 devicePixelRatio 屬性來獲
咱們能夠認爲:
devicePixelRatio 標記是: 標準顯示單元/當前設備的顯示單元
創建在上面的基礎上面, 你就能夠動態的調整元素的大小, 好比說某個元素 x 的寬度是 100px;
在 devicePixelRatio = 1 的設備上面寬度是 100px
在 devicePixelRatio = 2 的設備上面寬度就要是 200px;
ok, 那麼咱們來搞.
根據不一樣的 devicePixelRatio 來調整元素的樣式.
var box = document.querySelector('.box'); var height = parseInt(getComputedStyle(box).height); var width = parseInt(getComputedStyle(box).width); box.style.height = height * parseInt(window.devicePixelRatio) + 'px'; box.style.width = width * parseInt(window.devicePixelRatio) + 'px';
這僅僅是一個元素的兩個屬性, 1000個元素, 每一個元素 5 個屬性, 就可讓你哭掉了.
因此這種處理方式確定是不能夠的.
而後咱們發現了 rem 單位.
它的簡單解釋:
當你給某個元素A 設置了 height:2rem 的時候 它會找到根節點(html) 的 font-size 值, 好比是 16px 而後拿 16 * 2 = 32px 做爲元素A 的最終 height.
這個就能夠利用了
1 讓元素使用 rem 做單位
2 而後控制根元素的 font-size 值, 在不一樣的 devicePixelRatio 下面的時候, 呈現不一樣的值
好比你能夠設置:
devicePixelRatio = 1, font-size(root) = 100px; devicePixelRatio = 2, font-size(root) = 200px;
元素在這個時候, 就會自動響應大小的變化.
好, 開始搞:
var fontSize = 100 * parseInt(window.devicePixelRatio) + 'px'; document.documentElement.style.fontSize = fontSize;
嗯, 結果仍是不錯的, 在不一樣的分辨率下面, 咱們也能實現頁面相同了.
實際上, 上面的討論, 已經解決了咱們的問題:
在相同物理尺寸下的設備, 如何在分辨率不一樣的狀況下, 讓一個 100px 的元素, 它對應的物理世界的
大小, 始終相同?
如今更近一步, 上面的討論, 固定了一個變量: 屏幕尺寸, 如今放開這個變量, 固定屏幕的分辨率這個變量.
這個問題就變成適配問題了:
場景描述:
好比你的一個頁面原本是以 375寬度爲基礎作出來的, 那麼在設備的寬度變成 320px 的時候,
你的頁面就會出現問題: 擠壓, 變形, 錯亂, 或者超出隱藏, 超出滾動等等操做.
怎麼辦啊?
但願的是在 320 也能正常顯示: 讓頁面上的全部元素都縮小一些, 也就ok了. 好比一個元素
在 375 設備上面顯示這麼大, 在 320 上面顯示成這麼大不就好了.
那麼如何縮小?
rem;
你想下, 只要在屏幕的寬度變小的時候, 讓根元素的 font-size 跟着變小, 那麼全部使用 rem 做爲單位的
元素, 是否是也跟着變小, 目標就達成了.
那麼怎麼讓 font-size(root) 隨着屏幕的寬度變小而變小啊.
選一對基準值, 好比: 375px/100px; 表示屏幕寬度爲 375的時候, font-size(root) 爲 100;
每次計算一下就好, 好比發現屏幕的當前寬度爲 320, 那麼算不出來此時的 font-size(root) 嗎??
算出來不會設置根元素的 font-size 嗎?
好吧, 上面說的暫時都不要試, 先提一個事情.
全部的上面的討論, 實際上都創建在:
當你屏幕的分辨率是 100100 的時候, 你就擁有一份 100100 大小的容器, 用來呈現你的網頁.
好比說, 你的 iPhone7 的分辨率是 6671334, 那麼你就擁有一份 6671334 大小的容器來放你的網頁
惋惜並非這樣的.
從 iPhone 發佈前夕提及:
開發人員發現, 本來爲 pc 開發的網頁 在 iPhone 上面顯示不全, 這部分能夠經過滾動條來解決. 可是使用 百分比佈局的頁面就坑爹了, 本來在 pc 端瀏覽器上擁有 的 20% 在 iPhone 上面就一點點了, 佈局徹底亂了, 坑啊. 爲了解決這個問題, 開發人員提出了一個的新的玩意: 'layout viewport'
我該怎麼解釋這個玩意呢.
============== // 這個是你的百分比頁面所基於的寬度 === // 這個是你屏幕的寬度
這樣一來, 頁面確定會錯亂. 因此提出的 layout viewport 把模型變成這樣:
============== // 這個是你的百分比頁面所基於的寬度 ============= // layout viewport 的寬度 === // 這個是你屏幕的寬度
你的頁面會被放到 layout viewport 這個容器上面, 而後再將 layout viewport 縮小到
和屏幕寬度同樣的大小.
而且容許用戶放大頁面,經過滾動條滑動來瀏覽器所有頁面.
在最初的時候, 這種方式的確解決了 pc 端頁面在手機上瀏覽的問題, 可是隨着移動端的興起,
大量的針對移動端的頁面被製做出來, 也就是模型變成這樣:
=== // 針對移動端作的頁面 ============ // layout viewport === // 屏幕的寬度
這樣很明顯就出現問題了: 你的頁面先放到 layout viewport 上面, 而後又縮小到和屏幕寬度一致
最終顯示出來的, 就是你的頁面明顯被縮小了.
因此咱們要解決這個問題, 要把 layout viewport 的大小, 變成和屏幕的寬度一致.
這裏假設屏幕的顯示單元始終是標準的顯示單元大小。
怎麼讓 layout viewport 變成和屏幕的寬度一致呢?
經過 meta name="viewport" 標籤.
解釋一下:
meta name="viewport" 有一個 content 屬性, 它裏面有幾個值, 能夠用來對 layout viewport
作處理. content 有以下幾個字段:
initial-scale: 這個值會影響最終 layout viewport 的寬度, 計算公式應該是這樣:
屏幕的分辨率/(devicePixelRatio*initial-scale) = 最終的 layout viewport 的寬度.
屏幕的分辨率咱們能夠拿到, devicePixelRatio 也能夠拿到.
好比 iPhone7, 屏幕分辨率是 750*1334, devicePixelRatio=2, 當你設置 initial-scale=1 的時候
layout viewport 的最終寬度就是 375;
這裏有一個點, 我說一下;
咱們可讓 layout viewport 的寬度是任意值, 經過對 initial-scale 的設置.
那咱們要設置它爲多少呢?
能夠設置成 375, 這個寬度, 是以標準顯示單元爲單位算出來的寬度
也能夠設置成 750, 這樣的話, 你的 1px 就完整對應這個設備的 1 個顯示單元.
咱們選擇後者, 由於這個牽涉到 1px border 的實現.
若是設置成這個, 那麼你的 initial-scale 始終只要設置成 1/devicePixelRatio 便可,
由於 devicePixelRatio * 1/devicePixelRatio = 1;
還有其餘的兩個相關屬性:
maximum-scale: 最大能放大多少
minimum-scale: 最小能放大多少
但願不能縮放, 由於咱們的頁面不須要縮放就能正常顯示, 縮放了反而顯示不正確。
最終統籌一下:
咱們要作的事情
1 讓 layout viewport 變成和屏幕分辨率一致的寬度
2 根據設備寬度和 devicePixelRatio 來指明根元素的 font-size 值
這些操做以後, 你就能夠實現最終的代碼了.