display none的元素重新展示如何撑开页面_寻根问底之——元素隐藏你知多少?
老生常談之display: none
相信小伙伴們都被問(wèn)過(guò)這樣一個(gè)問(wèn)題:讓一個(gè)元素隱藏起來(lái),有多少種方法呢?常規(guī)來(lái)講,我們有三種方法display: none、opacity: 0和visibility: hidden,基于display: none的副作用,已經(jīng)是個(gè)被說(shuō)爛的問(wèn)題,主要是有以下缺點(diǎn):
一、切換顯隱時(shí)會(huì)導(dǎo)致reflow(回流),從而引起repaint(重繪),當(dāng)頁(yè)面中reflow增多至一定程度時(shí),會(huì)導(dǎo)致cpu使用率飆高。
二、無(wú)法對(duì)元素設(shè)置過(guò)渡動(dòng)畫(huà),也無(wú)法進(jìn)行方位測(cè)量(包括clientWidth, clientHeight, offsetWidth, offsetHeight, scrollWidth, scrollHeight, getBoundingClientRect(), getComputedStyle())
原因是:瀏覽器會(huì)解析HTML標(biāo)簽生成DOM Tree,解析CSS生成CSSOM,然后將DOM Tree和CSSOM合并生成Render Tree,最后才根據(jù)Render Tree的信息布局來(lái)渲染界面,但設(shè)置了display: none的元素,是不會(huì)被加入Render Tree中的,自然也無(wú)法渲染過(guò)渡動(dòng)畫(huà)。
三、用它來(lái)設(shè)置顯隱切換時(shí),會(huì)因?yàn)榕cdisplay: flex、display: grid沖突而使人困擾。
你真的了解opacity和visibility嗎
如此說(shuō)來(lái),我們?cè)O(shè)置元素顯隱時(shí),使用opacity或visibility似乎是更好的選擇,但小伙伴們有沒(méi)有考慮過(guò),opacity: 0和visibility: hidden這兩者又有何具體區(qū)別呢? 既然標(biāo)題寫(xiě)著尋根問(wèn)底,那么我們就通過(guò)幾輪PK來(lái)深挖一下這兩者的具體區(qū)別:
第一輪:動(dòng)畫(huà)屬性
常見(jiàn)的動(dòng)畫(huà)效果中,使用最廣泛的應(yīng)該就屬淡入和淡出了,這時(shí)候,我們應(yīng)該只有一種選擇:opacity配合animation,因?yàn)関isibility這個(gè)屬性是無(wú)法進(jìn)行動(dòng)畫(huà)過(guò)渡的,要滿足動(dòng)畫(huà)過(guò)渡,必須在兩個(gè)值之間存在連續(xù)不斷的值,即連續(xù)區(qū)間,visibility顯然不滿足,因?yàn)樵诳梢?jiàn)/不可見(jiàn)兩個(gè)狀態(tài)之間不存在中間態(tài),它是“布爾隱藏”的。
第二輪:子元素的表現(xiàn)
設(shè)置了opacity: 0和visibility: hidden的元素,它們的子元素會(huì)受到怎樣的不同影響呢?
首先,opacity屬性是不可以被子元素繼承的,而visibility屬性可以被繼承,詳見(jiàn)CSS3規(guī)范opacity和visibility中的屬性介紹。
其次,一旦父級(jí)元素設(shè)置了opacity,那么子元素的最大透明度將無(wú)法超過(guò)父級(jí),意味著,父級(jí)的opacity為0.5,那么子級(jí)的opacity就算設(shè)置為1,其實(shí)際透明度也會(huì)是0.5 * 1 = 0.5,所以,只要父級(jí)透明度為0,那么子級(jí)沒(méi)有任何辦法可以重新設(shè)置為可見(jiàn);
但visibility的子級(jí)卻仍有“翻身”的機(jī)會(huì),即使父級(jí)元素設(shè)置了visibility: hidden,子元素仍可通過(guò)visibility: visible重新設(shè)置為可見(jiàn)。
第三輪:層疊上下文(Stacking Context)
HTML中的元素都有自身的層疊水平,但是某些情況下,元素會(huì)形成層疊上下文(接下來(lái)用SC代替),直接“拔高”自身以及子元素的層疊水平。而元素間不同的層疊水平,在它們發(fā)生重疊的時(shí)候,就會(huì)決定誰(shuí)將在Z軸上更高一籌,也就是誰(shuí)離用戶的眼睛更近。
至于什么情況下元素會(huì)形成SC,可以參考MDN文檔的詳細(xì)說(shuō)明。而在這份文檔中我們可以看到:當(dāng)元素的opacity屬性值小于1時(shí),會(huì)形成SC。我們可以觀察如下代碼:
<div style="position: relative;"><div style="position: absolute;background: green;top: 0;width: 200px;height: 200px"></div><div style="background: red;width: 100px;height: 100px"></div> </div>這種情況下,設(shè)置了絕對(duì)定位的綠色方塊形成了SC,所以其層疊水平自然比紅色方塊高,所以此時(shí)我們看不到紅色方塊:
而當(dāng)我們?yōu)榧t色方塊設(shè)置了opacity屬性后,比如:
<div style="position: relative;"><div style="position: absolute;background: green;top: 0;width: 200px;height: 200px"></div><div style="opacity: 0.5;background: red;width: 100px;height: 100px"></div> </div>此時(shí),紅色方塊會(huì)層疊在綠色方塊之上。因?yàn)榧t色方塊的opacity小于1,形成了SC,且兩者都未設(shè)置z-index,屬于相同層疊水平,所以按照后來(lái)居上的原則,紅色方塊就會(huì)疊在上方,如圖所示:
同理,opacity為0的元素也會(huì)創(chuàng)建SC,而visibility屬性則不會(huì)創(chuàng)建SC,也不會(huì)影響到元素的層疊水平。
說(shuō)了半天,有人可能會(huì)問(wèn),既然元素都隱藏了,看不見(jiàn)了,誰(shuí)還管它在上在下呢?通常情況下是如此,但經(jīng)過(guò)第四輪的PK后,你就會(huì)知道,有時(shí)候你的確不能忽視這個(gè)問(wèn)題。
第四輪:可交互性/可訪問(wèn)性
這一輪我們比較的是可交互性/可訪問(wèn)性,先說(shuō)visibility: hidden,設(shè)置了這個(gè)屬性的元素,其綁定的監(jiān)聽(tīng)事件將會(huì)忽略event.target為自身的事件觸發(fā)。這句話比較拗口,通俗點(diǎn)說(shuō)就是,這個(gè)元素會(huì)接收到子元素的事件冒泡,但無(wú)法觸發(fā)自身的事件,可以通過(guò)這個(gè)在線demo體驗(yàn)一下這個(gè)效果。
當(dāng)然,除了無(wú)法觸發(fā)自身的事件之外,它還無(wú)法通過(guò)tab鍵訪問(wèn)到,也就是無(wú)法focus;此外,它還會(huì)失去accessibility,也就是不能進(jìn)行無(wú)障礙訪問(wèn),比如屏幕閱讀軟件將無(wú)法訪問(wèn)到這個(gè)元素。
反觀設(shè)置了opacity: 0的元素,則完全沒(méi)有以上的限制。現(xiàn)在你知道我們?yōu)樯恫荒芎鲆暽弦惠喬岢龅膯?wèn)題了,因?yàn)樵O(shè)置了opacity: 0的元素即使看不見(jiàn)了,它仍然可以被點(diǎn)擊被訪問(wèn),有時(shí)會(huì)產(chǎn)生意料之外的bug。
取長(zhǎng)補(bǔ)短
既然兩者都有各自的優(yōu)缺點(diǎn),我們能否將其結(jié)合,并取長(zhǎng)補(bǔ)短呢?
答案是當(dāng)然可以。但首先要明確我們想取什么長(zhǎng),補(bǔ)什么短。一般來(lái)講,我們既希望元素可以使用淡入淡出的動(dòng)畫(huà)效果,又希望在消失后不要保留可交互性/可訪問(wèn)性,其實(shí)做法很簡(jiǎn)單:
.box {animation: fade 0.5s linear 0s forwards; } @keyframes fade {0% {opacity: 1;}100% {opacity: 0;visibility: hidden;} }我們?nèi)匀皇褂胦pacity來(lái)做動(dòng)畫(huà)過(guò)渡,但在最后一個(gè)動(dòng)畫(huà)幀,我們把visibility: hidden加上,就可以達(dá)到我們想要的效果了。此時(shí),當(dāng)元素淡出后,也不會(huì)意外地觸發(fā)事件了。并且,在使用opacity屬性進(jìn)行動(dòng)畫(huà)效果時(shí),瀏覽器還會(huì)將該元素提升為composite layer(合成層),使用gpu進(jìn)行硬件加速渲染,兩全其美~
當(dāng)然,如果你的確需要這個(gè)元素保留頁(yè)面中的占位,就不能這樣做了。
總結(jié)
總而言之,如果你沒(méi)有動(dòng)畫(huà)需求,使用visibility進(jìn)行顯隱切換可能更省心,但如果有動(dòng)畫(huà)需求,則最好使用兩者結(jié)合的方式。另外,以后會(huì)有更多的尋根問(wèn)底系列的文章,目的就是要對(duì)小的知識(shí)點(diǎn)也進(jìn)行深入剖析,從而獲得更加系統(tǒng)性的認(rèn)識(shí),而不是停留在表面。
ps:歡迎關(guān)注微信公眾號(hào)——前端漫游指南,會(huì)定期發(fā)布優(yōu)質(zhì)原創(chuàng)文章和譯文,關(guān)注公眾號(hào)福利:回復(fù)666可以獲得精選前端進(jìn)階電子書(shū),感謝~
總結(jié)
以上是生活随笔為你收集整理的display none的元素重新展示如何撑开页面_寻根问底之——元素隐藏你知多少?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux父子进程之间之间的区别与联系
- 下一篇: u盘启动pxe安装linux,U盘启动安