在 web 的世界裏,無線和 PC 的響應式適配實際上是兩個世界……javascript
viewport 解釋爲中文就是‘視口’的意思,也就是瀏覽器中用於顯示網頁的區域。在 PC 端,其大小也就是瀏覽器可視區域的大小,因此咱們也不會太關注此概念;而在移動端,絕大多數狀況下 viewport 都大於瀏覽器可視區,保證 PC 頁面在移動瀏覽器上面的可視性。爲提高可視性體驗,針對移動端有了對 viewport 的深刻研究。css
在移動端有三種類型的 viewport: layoutviewport、visualviewport、idealviewport。具體解釋以下:html
咱們經過對幾種 viewport 設置能夠對網頁的展現進行有效的控制,在移動端咱們常常會在 head 標籤中看到這段代碼:html5
<meta name='viewport' content='width=device-width,initial-scale=1,user-scale=no' />
複製代碼
經過對 meta 標籤三個 viewport 的設置,最終使頁面完美展現。下面詳細的闡釋其具體含義:java
對上面的說明經過公式推導進行進一步的解釋:web
// 設定兩個變量:
viewport_1 = width;
viewport_2 = idealviewport / initial-scale;
// 則:
layoutviewport = max{viewport_1, viewport_2};
visualviewport = viewport_2;
複製代碼
只要 layoutviewport === visualviewport,頁面下面不會出現滾動條,默認只是把頁面放大或縮小。瀏覽器
如下是經過改變 meta viewport 的幾個參數的值來算取不一樣的 viewport:app
width | initial-scale | layoutviewport | visualviewport | idealviewport | 是否滾動 |
---|---|---|---|---|---|
- | - | 980px | 980px | 375px | 否 |
device-width | 1 | 375px | 375px | 375px | 否 |
device-width | 2 | 375px | 188px | 375px | 是 |
device-width | 0.5 | 750px | 750px | 375px | 否 |
480px | 1 | 480px | 375px | 375px | 是 |
480px | 2 | 480px | 188px | 375px | 是 |
480px | 0.5 | 750px | 750px | 375px | 否 |
以上是針對 iphone 6/7/8 的測試數據,且不管怎麼設置 viewport 都具備臨界值,即:75 <= layoutviewport <= 10000,75 <= visualviewport <= 1500。iphone
viewport 的設置不會對 PC 頁面產生影響,但對於移動頁面卻很重要。下面咱們舉例來講明:ide
手機屏幕上顯示的最小單元,該最小單元具備顏色及亮度的屬性可供設置,iphone六、七、8 爲:750 * 1334,iphone6+、7+、8+ 爲 1242 * 2208
此爲邏輯像素,計算機設備中的一個點,css 中設置的像素指的就是該像素。老早在沒有 retina 屏以前,設備獨立像素與物理像素是相等的。
設備像素比(dpr) = 物理像素/設備獨立像素。如 iphone 六、七、8 的 dpr 爲 2,那麼一個設備獨立像素便爲 4 個物理像素,所以在 css 上設置的 1px 在其屏幕上佔據的是 2個物理像素,0.5px 對應的纔是其所能展現的最小單位。這就是 1px 在 retina 屏上變粗的緣由,目前有不少辦法來解決這一問題。
從第一部分的討論可知 viewport 的 initial-scale 具備縮放頁面的效果。對於 dpr=2 的屏幕,1px壓縮一半即可與1px的設備像素比匹配,這就能夠經過將縮放比 initial-scale 設置爲 0.5=1/2 而實現。以此類推 dpr=3的屏幕能夠將 initial-scale設置爲 0.33=1/3 來實現。
結合 二、3 部分能夠實現 1px 的物理像素這一最小屏幕單位,那在此基礎上如可以讓設計一般提供的 750px 設計稿來完美的適配到多種機型上,使用 rem 是一種解決方式。
rem 是相對於根元素 html 的 font-size 來作計算。一般在頁面初始化時加載時經過對document.documentElement.style.fontSize
設置來實現。
經過對 initial-scale = 1/dpr 的設置,已將對屏幕的描述從物理像素轉化到了物理像素上了,這將是後續推導的基礎,且設計稿爲 750px。
所以可推導出 rem 的設定方式:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
複製代碼
下面咱們將 750px 下,1rem 表明的像素值用 baseFont 表示,則在 baseFont = 75 的狀況下,是分紅 10 等份的。所以能夠將上面的公式通用話一些:
document.documentElement.style.fontSize = document.documentElement.clientWidth / ( 750 / 75 ) + 'px';
複製代碼
總體設置可參考以下代碼:
(function (baseFontSize) {
const _baseFontSize = baseFontSize || 75;
const ua = navigator.userAgent;
const matches = ua.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i);
const isIos = navigator.appVersion.match(/(iphone|ipad|ipod)/gi);
const dpr = window.devicePixelRatio || 1;
if (!isIos && !(matches && matches[1] > 534)) {
// 若是非iOS, 非Android4.3以上, dpr設爲1;
dpr = 1;
}
const scale = 1 / dpr;
const metaEl = document.querySelector('meta[name="viewport"]');
if (!metaEl) {
metaEl = document.createElement('meta');
metaEl.setAttribute('name', 'viewport');
window.document.head.appendChild(metaEl);
}
metaEl.setAttribute('content', 'width=device-width,user-scalable=no,initial-scale=' + scale + ',maximum-scale=' + scale + ',minimum-scale=' + scale);
document.documentElement.style.fontSize = document.documentElement.clientWidth / (750 / _baseFontSize) + 'px';
})();
複製代碼
同時爲了書寫方即可以直接經過 px 佈局,而後在打包時利用 pxtorem 庫轉化爲基於 rem 的佈局。
將視口寬度 window.innerWidth
和視口高度 window.innerHeight
等分爲 100 份,且將這裏的視口理解成 idealviewport 更爲貼切,並不會隨着 viewport 的不一樣設置而改變。
若是設計稿爲 750px,那麼 1vw = 7.5px,100vw = 750px。其實設計稿按照設麼都沒多大關係,最終轉化過來的都是相對單位,上面講的 rem 也是對它的模擬。這裏的比例關係也推薦不要本身換算,使用 pxtoviewport 的庫就能夠幫咱們轉換。固然每種方案都會有其弊端,這裏就不展開討論。
在移動端開發中,理解視口對適配相當重要。所以本文先從視口展開討論,從而引出 1px、rem 及 vw/vh 這些和適配相關的主要話題。下面提供的參考文章會在某些點上更加細化,以供參考。
www.quirksmode.org/mobile/view…