視窗單位一直都存在爭議,部分原因是因為移動端瀏覽器對如何實現(xiàn)視窗單位有著自己的看法,這樣就讓本來簡單的事情變得更加復(fù)雜化。
一個典型的示例是:
vw的計算是否要包含瀏覽器的滾動條?
那么網(wǎng)站的導(dǎo)航或頁面控件呢?
這些應(yīng)該算在計算中嗎?
還有一些設(shè)備本身的物理屬性(比如iPhone X的劉海)是不容忽視的。
首先,了解一下背景
有關(guān)于如何計算視窗單位的規(guī)范描述的相當(dāng)模糊。對于移動設(shè)備,我們通常關(guān)心的是高度,所以讓我們具體來看一下視窗單位中的vh:
vh unit:Equal to 1% of the height of the initial containing block.
直譯過來,大致的意思是“vh等于初始包含塊高度的1%”。
所以,在處是設(shè)備和特定的瀏覽器的區(qū)別方面,沒有明確的指導(dǎo)。
vh最初是由瀏覽器的當(dāng)前視窗計算的。如果你打開瀏覽器開始加載一個網(wǎng)站,1vh等于你屏幕高度的1%(減去瀏覽器界面)。
1vh = window.innerHeight。
但是!如果你開始滾動,那就另當(dāng)別論了。一旦你通過了一個瀏覽器界面,比如地址欄,vh值就會更新,結(jié)果就是內(nèi)容的跳躍。
iOS的Safari瀏覽器是最早更新其實現(xiàn)的移動端瀏覽器之一,它選擇根據(jù)屏幕的最大高度為vh的計算值(為vh定義一個固定值)。這樣,一旦地址欄離開視窗,用戶在頁面上也不會看到內(nèi)容的閃跳。
雖然使用固定值很好,但這也意味著如果地址欄在視窗中,就不能有一個全屏高度的元素。元素的底部將被裁剪。
正如上圖所示,當(dāng)?shù)刂窓谠谝暣爸袝r(左圖),元素的底部被裁剪,但我們想要的是元素底部不被裁剪(右圖)。
CSS自定義屬性:調(diào)整大小的技巧
我突然想到,CSS自定義屬性和幾行JavaScript代碼可能是獲得所需的一致和正確大小的完美解決方案。
在JavaScript中,你始終可以使用全局變量window.innerHeight獲得當(dāng)前視窗的值。這個值考慮了瀏覽器的界面,并在其可見性(visibility)發(fā)生變化時進(jìn)行了更新。訣竅就是將視窗(viewport)值存儲在CSS自定義屬性(CSS變量)中,并將其應(yīng)用于元素,而不是vh單位。
假設(shè)我們在例子中設(shè)置一個CSS自定義屬性:--vh。這意味著我們將在CSS像下面這樣使用這個自定義屬性:
.my-element {
height: 100vh; /* 為不支持自定義屬性的瀏覽器做降級處理 */
height: calc(var(--vh, 1vh) * 100);
}
好了,這就搞定了,就是這么的簡單。現(xiàn)在讓我們使用JavaScript來獲得視窗的內(nèi)部高度(window.innerHeight):
// 首先獲取視窗高度,再乘以1%得到vh單位的值
let vh = window.innerHeight * 0.01;
// 把--vh的值設(shè)置到文檔的根元素中
document.documentElement.style.setProperty('--vh', `${vh}px`);
因此,我們告訴JavaScript獲取視窗的高度,然后占這個值的1%,所以我們就可以將值指定為視窗高度單位值。然后使用JavaScript在:root中創(chuàng)建CSS自定義屬性--vh。
因此,我們現(xiàn)在就可以像使用其他單位一樣使用--vh作為高度值,然后乘以100就能得到我們想要的高度值。
親自體驗一下,調(diào)整視窗的高度,在根元素html中可以看到--vh值是動態(tài)變化的:
還有一個小細(xì)節(jié)
雖然我們的工作看上去已經(jīng)完成了,但是對于追求細(xì)節(jié)的同學(xué)而言,可能已經(jīng)發(fā)現(xiàn)了,當(dāng)視窗的高度改變時,不會自動更新元素的大小。那么我們接著在上面的示例上進(jìn)行調(diào)整。
我們可以監(jiān)聽window的resize事件來更新--vh的值。如果用戶旋轉(zhuǎn)設(shè)備屏幕,比如從橫向到縱向,或者導(dǎo)航移動到滾動視窗之外,這樣就非常方便。
// 監(jiān)聽resize事件
window.addEventListener('resize', () => {
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
更新--vh的值將會觸發(fā)頁面重繪,用戶可能會感覺頁面在跳動。因此,我并不是說這個技巧應(yīng)該用于每個項目,或者替換vh單位的所有用法,但是只有當(dāng)你需要你的用戶擁有一個確切的視窗單位值時才使用。
此外,你可能希望resize事件實現(xiàn)debounce方法,以避免在用戶調(diào)整瀏覽器窗口大小時觸發(fā)許多事件。
如沒特殊注明,文章均為方維網(wǎng)絡(luò)原創(chuàng),轉(zhuǎn)載請注明來自http://m.oulysa.com/news/6561.html