在 web 的世界里,無線和 PC 的響應(yīng)式適配其實(shí)是兩個(gè)世界……
1. 視口 viewport
1.1 viewport 基礎(chǔ)
viewport 解釋為中文就是‘視口’的意思,也就是瀏覽器中用于顯示網(wǎng)頁的區(qū)域。在 PC 端,其大小也就是瀏覽器可視區(qū)域的大小挤渔,所以我們也不會(huì)太關(guān)注此概念;而在移動(dòng)端,絕大多數(shù)情況下 viewport 都大于瀏覽器可視區(qū)骡男,保證 PC 頁面在移動(dòng)瀏覽器上面的可視性。為提升可視性體驗(yàn)傍睹,針對移動(dòng)端有了對 viewport 的深入研究隔盛。
1.2 viewport 詳解
在移動(dòng)端有三種類型的 viewport: layoutviewport、visualviewport拾稳、idealviewport吮炕。具體解釋如下:
layoutviewport:? 大于實(shí)際屏幕, 元素的寬度繼承于 layoutviewport访得,用于保證網(wǎng)站的外觀特性與桌面瀏覽器一樣龙亲。layoutviewport 到底多寬,每個(gè)瀏覽器不同悍抑。iPhone 的 safari 為 980px鳄炉,通過 document.documentElement.clientWidth 獲取。
visualviewport: 當(dāng)前顯示在屏幕上的頁面搜骡,即瀏覽器可視區(qū)域的寬度拂盯。
idealviewport: 為瀏覽器定義的可完美適配移動(dòng)端的理想 viewport,固定不變记靡,可以認(rèn)為是設(shè)備視口寬度磕仅。比如 iphone 7 為 375px, iphone 7p 為 414px。
1.3 viewport 設(shè)置
我們通過對幾種 viewport 設(shè)置可以對網(wǎng)頁的展示進(jìn)行有效的控制簸呈,在移動(dòng)端我們經(jīng)常會(huì)在 head 標(biāo)簽中看到這段代碼:
復(fù)制代碼
通過對 meta 標(biāo)簽三個(gè) viewport 的設(shè)置克伊,最終使頁面完美展示吃嘿。下面詳細(xì)的闡釋其具體含義:
width 設(shè)置的是 layoutviewport 的寬度
initial-scale 設(shè)置頁面的初始縮放值,并且這個(gè)初始縮放值是相對于 idealviewport 縮放的,最終得到的結(jié)果不僅會(huì)決定 visualviewport瞳筏,還會(huì)影響到 layoutviewport
user-scalable 是否允許用戶進(jìn)行縮放的設(shè)置
對上面的說明通過公式推導(dǎo)進(jìn)行進(jìn)一步的解釋:
// 設(shè)定兩個(gè)變量:? viewport_1 = width;? viewport_2 = idealviewport / initial-scale;// 則:? layoutviewport = max{viewport_1, viewport_2};? visualviewport = viewport_2;復(fù)制代碼
只要 layoutviewport === visualviewport绢馍,頁面下面不會(huì)出現(xiàn)滾動(dòng)條,默認(rèn)只是把頁面放大或縮小。
1.4 viewport 舉例
以下是通過改變 meta viewport 的幾個(gè)參數(shù)的值來算取不同的 viewport:
widthinitial-scalelayoutviewportvisualviewportidealviewport是否滾動(dòng)
--980px980px375px否
device-width1375px375px375px否
device-width2375px188px375px是
device-width0.5750px750px375px否
480px1480px375px375px是
480px2480px188px375px是
480px0.5750px750px375px否
以上是針對 iphone 6/7/8 的測試數(shù)據(jù)丛楚,且無論怎么設(shè)置 viewport 都具有臨界值,即:75 <= layoutviewport <= 10000憔辫,75 <= visualviewport <= 1500趣些。
1.5 為什么要設(shè)置 viewport
viewport 的設(shè)置不會(huì)對 PC 頁面產(chǎn)生影響,但對于移動(dòng)頁面卻很重要贰您。下面我們舉例來說明:
媒體查詢 @media
響應(yīng)式布局中坏平,會(huì)根據(jù)媒體查詢功能來適配多端布局,必須對 viewport 進(jìn)行設(shè)置锦亦,否則根據(jù)查詢到的尺寸無法正確匹配視覺寬度而導(dǎo)致布局混亂舶替。如不設(shè)置 viewport 參數(shù),多說移動(dòng)端媒體查詢的結(jié)果將是 980px 這個(gè)節(jié)點(diǎn)布局的參數(shù)杠园,而非我們通常設(shè)置的 768px 范圍內(nèi)的這個(gè)布局參數(shù)
由于目前多數(shù)手機(jī)的 dpr 都不再是 1顾瞪,為了產(chǎn)出高保真頁面,我們一般會(huì)給出 750px 的設(shè)計(jì)稿抛蚁,那么就需要通過設(shè)置 viewport 的參數(shù)來進(jìn)行整體換算陈醒,而不是在每次設(shè)置尺寸時(shí)進(jìn)行長度的換算。
2. 設(shè)備像素比 dpr 與 1px 物理像素
2.1 物理像素(physical pixel)
手機(jī)屏幕上顯示的最小單元瞧甩,該最小單元具有顏色及亮度的屬性可供設(shè)置孵延,iphone6、7亲配、8 為:750 * 1334尘应,iphone6+、7+吼虎、8+ 為 1242 * 2208
2.2 設(shè)備獨(dú)立像素(density-indenpendent pixel)
此為邏輯像素犬钢,計(jì)算機(jī)設(shè)備中的一個(gè)點(diǎn),css 中設(shè)置的像素指的就是該像素思灰。老早在沒有 retina 屏之前玷犹,設(shè)備獨(dú)立像素與物理像素是相等的。
2.3 設(shè)備像素比(device pixel ratio)
設(shè)備像素比(dpr) = 物理像素/設(shè)備獨(dú)立像素洒疚。如 iphone 6歹颓、7、8 的 dpr 為 2油湖,那么一個(gè)設(shè)備獨(dú)立像素便為 4 個(gè)物理像素巍扛,因此在 css 上設(shè)置的 1px 在其屏幕上占據(jù)的是 2個(gè)物理像素,0.5px 對應(yīng)的才是其所能展示的最小單位乏德。這就是 1px 在 retina 屏上變粗的原因撤奸,目前有很多辦法來解決這一問題吠昭。
2.4 1px的物理像素的解決方案
從第一部分的討論可知 viewport 的 initial-scale 具有縮放頁面的效果。對于 dpr=2 的屏幕胧瓜,1px壓縮一半便可與1px的設(shè)備像素比匹配矢棚,這就可以通過將縮放比 initial-scale 設(shè)置為 0.5=1/2 而實(shí)現(xiàn)。以此類推 dpr=3的屏幕可以將 initial-scale設(shè)置為 0.33=1/3 來實(shí)現(xiàn)府喳。
3. 設(shè)備像素比 dpr 與 rem 的適配方案
結(jié)合 2蒲肋、3 部分可以實(shí)現(xiàn) 1px 的物理像素這一最小屏幕單位,那在此基礎(chǔ)上如可讓設(shè)計(jì)通常提供的 750px 設(shè)計(jì)稿來完美的適配到多種機(jī)型上钝满,使用 rem 是一種解決方式兜粘。
3.1 rem 如何設(shè)置
rem 是相對于根元素 html 的 font-size 來做計(jì)算。通常在頁面初始化時(shí)加載時(shí)通過對document.documentElement.style.fontSize設(shè)置來實(shí)現(xiàn)舱沧。
3.2 rem 適配規(guī)則
通過對 initial-scale = 1/dpr 的設(shè)置,已將對屏幕的描述從物理像素轉(zhuǎn)化到了物理像素上了偶洋,這將是后續(xù)推導(dǎo)的基礎(chǔ)熟吏,且設(shè)計(jì)稿為 750px。
物理像素為 750 = 375 * 2玄窝,若屏幕等分為 10 份牵寺,那么 1rem = 75px,10rem = 750px;
物理像素為 1125 = 375 * 3恩脂,若屏幕等分為 10 份帽氓,那么 1rem = 112.5px, 10rem = 1125px;
物理像素為 1242 = 414 * 3, 若屏幕等分為 10 份,那么 1rem = 124.2px, 10rem = 1242px;
因此可推導(dǎo)出 rem 的設(shè)定方式:
document.documentElement.style.fontSize =document.documentElement.clientWidth /10+'px';復(fù)制代碼
下面我們將 750px 下俩块,1rem 代表的像素值用 baseFont 表示黎休,則在 baseFont = 75 的情況下,是分成 10 等份的玉凯。因此可以將上面的公式通用話一些:
document.documentElement.style.fontSize =document.documentElement.clientWidth / (750/75) +'px';復(fù)制代碼
整體設(shè)置可參考如下代碼:
(function(baseFontSize){const_baseFontSize = baseFontSize ||75;constua = navigator.userAgent;constmatches = ua.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i);constisIos = navigator.appVersion.match(/(iphone|ipad|ipod)/gi);constdpr =window.devicePixelRatio ||1;if(!isIos && !(matches && matches[1] >534)) {// 如果非iOS, 非Android4.3以上, dpr設(shè)為1;dpr =1;? ? }constscale =1/ dpr;constmetaEl =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';})();復(fù)制代碼
同時(shí)為了書寫方便可以直接通過 px 布局势腮,然后在打包時(shí)利用 pxtorem 庫轉(zhuǎn)化為基于 rem 的布局。
4. 視口單位適配方案
將視口寬度window.innerWidth和視口高度window.innerHeight等分為 100 份漫仆,且將這里的視口理解成 idealviewport 更為貼切捎拯,并不會(huì)隨著 viewport 的不同設(shè)置而改變。
vw : 1vw 為視口寬度的 1%
vh : 1vh 為視口高度的 1%
vmin :? vw 和 vh 中的較小值
vmax : 選取 vw 和 vh 中的較大值
如果設(shè)計(jì)稿為 750px盲厌,那么 1vw = 7.5px署照,100vw = 750px。其實(shí)設(shè)計(jì)稿按照設(shè)么都沒多大關(guān)系吗浩,最終轉(zhuǎn)化過來的都是相對單位建芙,上面講的 rem 也是對它的模擬。這里的比例關(guān)系也推薦不要自己換算懂扼,使用 pxtoviewport 的庫就可以幫我們轉(zhuǎn)換岁钓。當(dāng)然每種方案都會(huì)有其弊端,這里就不展開討論。
總結(jié)
在移動(dòng)端開發(fā)中屡限,理解視口對適配至關(guān)重要品嚣。因此本文先從視口展開討論,從而引出 1px钧大、rem 及 vw/vh 這些和適配相關(guān)的主要話題翰撑。下面提供的參考文章會(huì)在某些點(diǎn)上更加細(xì)化,以供參考啊央。
作者:阿里巴巴TXD
鏈接:https://juejin.im/post/5c0dd7ac6fb9a049c43d7edc
來源:掘金
著作權(quán)歸作者所有眶诈。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處瓜饥。