CSS中用 opacity、visibility、display 属性将 元素隐藏 的 对比分析
說明
opacity 用來設置透明度
display 定義建立布局時元素生成的顯示框類型
visibility 用來設置元素是否可見。
opacity、visibility、display 這三個屬性分別取值 0、hidden、none 都能使元素在頁面上看不見,但是他們在方方面面都還是有區別的。
是否占據頁面空間
舉個例子
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.yellow{width:100px;height:100px;background:yellow;}.red{width:100px;height:100px;background:red;}</style></head><body><div class="yellow"></div><div class="red"></div></body> </html>最開始的樣子
黃色塊div元素 使用 opacity:0; 時
黃色塊div元素 使用 visibility:hidden; 時
黃色塊div元素 使用 display:none; 時
可以看出,使用 opacity 和 visibility 屬性時,元素還是會占據頁面空間的,而使用 display 屬性時,元素不占據頁面空間。
對子元素的影響
如果子元素什么都不設置的話,都會受父元素的影響,和父元素的顯示效果一樣,我們就來舉例看看,如果子元素設置的值 和 父元素設置的值不同會有什么效果。
例子 (opacity屬性)
例子 (visibility屬性)
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.yellow{width:100px;height:100px;background:yellow;visibility:hidden; /* 父元素的 visibility屬性取值為hidden */}.blue{width:50px;height:50px;background:blue;visibility:visible; /* 子元素的 visibility屬性取值為visible */}</style></head><body><div class="yellow"><div class='blue'></div></div></body> </html>
例子 (display屬性)
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.yellow{width:100px;height:100px;background:yellow;display:none; /* 父元素的 display屬性取值為none */}.blue{width:50px;height:50px;background:blue;display:block; /* 子元素的 display屬性取值為block */}</style></head><body><div class="yellow"><div class='blue'></div></div></body> </html>
可以看出,使用 opacity 和 display 屬性時,父元素對子元素的影響很明顯,子元素設置的 opacity 和 display 屬性是不起作用的,顯示的效果和父元素一樣,而使用 visibility 屬性時,子元素如果設置為 visibility:visible; 并沒有受父元素的影響,可以繼續顯示出來。
自身綁定的事件是否能繼續觸發
這里說的觸發事件,是指用戶人為的觸發的事件,不包括使用 JavaScript 模擬觸發的事件。
例子 (opacity屬性)
例子 (visibility屬性)
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.yellow{width:100px;height:100px;background:yellow;visibility:hidden;}</style></head><body><div class="yellow" onmouseenter="alert(0)"></div></body> </html>
使用 display:none; 就不用舉例子了,因為使用 display 屬性的話,元素不僅看不見,而且也不占據頁面空間,所有不會觸發事件。
總的來說,使用 visibility 和 display 屬性,自身的事件不會觸發,而使用 opacity 屬性,自身綁定的事件還是會觸發的。
是否影響其他元素觸發事件
例子(opacity屬性)
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.red{width:400px;height:40px;background:red;position:relative;}.yellow{position:absolute; top:0;left:0;width:200px;height:300px;background:yellow;opacity:0; }.blue{width:200px;height:200px;background:blue;}.red:hover .yellow{opacity:1; }</style></head><body><div class='red'><div class='yellow'></div></div><p class='blue' onmouseenter=alert(0)></p></body> </html>
黃色塊div元素設置 opacity:0; ,通過定位,遮擋住了 藍色的p元素,當鼠標移到藍色p元素上時,并沒有觸發藍色p元素的事件。
例子(visibility屬性)
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.red{width:400px;height:40px;background:red;position:relative;}.yellow{position:absolute; top:0;left:0;width:200px;height:300px;background:yellow;visibility:hidden; }.blue{width:200px;height:200px;background:blue;}.red:hover .yellow{visibility:visible; }</style></head><body><div class='red'><div class='yellow'></div></div><p class='blue' onmouseenter=alert(0)></p></body> </html>
黃色塊div元素設置 visibility:hidden; ,通過定位,雖然遮擋住了 藍色的p元素,但是當鼠標移到藍色p元素上時,還是觸發了藍色p元素綁定的事件。
和上邊一樣,display 屬性就不舉例子了,因為他不會占據頁面空間,也就不會遮擋其他元素,就不會影響其他元素觸發事件了。
所以,visibility 和 display 屬性是不會影響其他元素觸發事件的,而 opacity 屬性 如果遮擋住其他元素,其他的元素就不會觸發事件了。
是否產生回流(reflow)
回流
當頁面中的一部分(或全部)因為元素的規模尺寸,布局,隱藏等改變而需要重新構建。這就稱為回流(也有人會把回流叫做是重布局或者重排)。每個頁面至少需要一次回流,就是在頁面第一次加載的時候。
dispaly 屬性會產生回流,而 opacity 和 visibility 屬性不會產生回流。
是否產生重繪(repaint)
重繪
當頁面中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響布局的時候,比如background-color。則稱為重繪。dispaly 和 visibility 屬性會產生重繪,而 opacity 屬性不一定會產生重繪。
元素提升為合成層后,transform 和 opacity 不會觸發 repaint,如果不是合成層,則其依然會觸發 repaint。
在 Blink 和 WebKit 內核的瀏覽器中,對于應用了 transition 或者 animation 的 opacity 元素,瀏覽器會將渲染層提升為合成層。
也可以使用 translateZ(0) 或者 translate3d(0,0,0) 來人為地強制性地創建一個合成層。
舉個例子
<!doctype html> <html lang="en"> <head><meta charset="UTF-8"> </head> <body><div id="target">重繪 repaint</div><script>var flag = false;setInterval(function () {flag = !flag;target.style.opacity = flag ? 0 : 1;},1000)</script> </body> </html>我們可以用 Chrome DevTools 的 Rendering 來看看,
先打開 Rendering
把第一個選項勾選,這個選項會 高亮顯示需要重繪的區域。
看看效果
改改代碼,增加上個 transition
<!doctype html> <html lang="en"> <head><meta charset="UTF-8"><style>div{transition:1s;}</style> </head> <body><div id="target">重繪 repaint</div><script>var flag = false;setInterval(function () {flag = !flag;target.style.opacity = flag ? 0 : 1;},1000)</script> </body> </html>再看看效果
加上 transition 后就沒有 高亮顯示了,這時候 opacity 不會觸發重繪。
實際上透明度改變后,GPU 在繪畫時只是簡單的降低之前已經畫好的紋理的 alpha 值來達到效果,并不需要整體的重繪。不過這個前提是這個被修改的 opacity 本身必須是一個圖層,如果圖層下還有其他節點,GPU 也會將他們透明化。注意:回流必將引起重繪,而重繪不一定會引起回流。
是否支持transition
opacity 是支持 transition的,一般淡入淡出的效果就是這樣實現的。
visibility 也是支持 transition 的。
visibility: 離散步驟,在0到1數字范圍之內,0表示“隱藏”,1表示完全“顯示”visibility : hidden; 可以看成 visibility : 0;
visibility : visible; 可以看成 visibility : 1;
只要 visibility 的值大于0就是顯示的,所以
visibility:visible 過渡到 visibility:hidden,看上去不是平滑的過渡,而是進行了一個延時。
而如果 visibility:hidden 過渡到 visibility:visible ,則是立即顯示,沒有延時。
注意
上面這個例子只能是從 visibility:visible 過渡到 visibility:hidden,不能從 visibility:hidden 過渡到 visibility:visible 。
當元素是 visibility:hidden; 時,自身的事件不會觸發,所以像上面這個例子中,直接在藍色塊div元素 上加 hover 事件,要去將自身的 visibility:hidden 過渡到 visibility:visible 是不會起作用的。
但是在其他元素上加事件,來將該元素的 visibility:hidden 過渡到 visibility:visible 是可以的,看例子。
display 不僅不支持transition,它還會使 transition 失效。舉個例子看看
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.blue{width:200px;height:200px;background:blue;}.yellow{width:100px;height:100px;background:yellow;opacity:0;display:none;transition:1s}.blue:hover .yellow{opacity:1;display:block;}</style></head><body><div class='blue'><div class='yellow'></div></div></body> </html>
可以看出用了display,支持 transition 的 opacity 屬性也沒起作用。
這是因為display:none; 的元素,是不會渲染在頁面上的,而 transition 要起作用,元素必須是已經渲染在頁面上的元素,我們可以再來看個例子
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.blue{width:200px;height:200px;background:blue;}.yellow{width:100px;height:100px;background:yellow;opacity:0;transition:1s}</style></head><body><span>渲染到頁面</span><div class='blue'></div><script> var span = document.querySelector('span');span.addEventListener('click',function(){var yellowDiv = document.createElement('div');yellowDiv.classList.add('yellow');var blue = document.querySelector('.blue');blue.appendChild(yellowDiv);yellowDiv.style.opacity = '1';})</script></body> </html>
給 span 元素綁定事件,點擊它的時候,才會把黃色塊div元素,渲染到DOM樹上,然后改變黃色塊div元素的 opacity 屬性,opacity 是支持 transition 的,而在這段代碼中,并沒有起作用。
更詳細的關于 transition 是否成功 的解讀看這里
渲染樹決定 transtion 能否成功
要想解決這個問題,我們可以這樣做。
1、把 display 屬性換成 visibility 屬性
2、如果必須要用 display 屬性,我們可以加上定時器來解決這個問題
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><style>.blue{width:200px;height:200px;background:blue;}.yellow{width:100px;height:100px;background:yellow;display:none;opacity:0;transition:1s;}</style></head><body><div class='blue'><div class='yellow'></div></div><script> var blue = document.querySelector('.blue');blue.addEventListener('mouseenter',function(){var yellowDiv = document.querySelector('.yellow');yellowDiv.style.display = 'block';setTimeout(function(){yellowDiv.style.opacity = '1';},0);})</script></body> </html>
總結
總結
以上是生活随笔為你收集整理的CSS中用 opacity、visibility、display 属性将 元素隐藏 的 对比分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rsync的配置应用
- 下一篇: 面试题: mysql 数据库已看 sql