背景
最近看到jQuery中获取隐藏元素的计算样式时,使用了visibility属性。 由于之前没有完全理解几种不同方法设置元素不可见性之间的区别,感觉平时的业务代码中也不会用到这些-_-(码农),这次碰到了,要好好研究一下。
浏览器构建渲染树
浏览器渲染页面前需要先构建DOM和CSSOM树,在不考虑JavaScript脚本的情况下,这两者分别由HTML和CSS来提供。 CSSOM树和DOM树合并成渲染树,然后用于计算每个可见元素的布局,并输出给绘制流程,将像素渲染到屏幕上。 所以,直接看到的实体就是渲染树,而所谓的元素的不可见指的是在渲染树上看不到该元素。
三种方法设置元素不可见
最初显示样式
html代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" >
<title>元素可见性测试</title>
<style>
.parent {
border: solid 1px #000000;
padding: 5px;
position: absolute;
top: 100px;
left: 100px;
}
.head {
border: solid 1px #0000FF;
width: 100px;
}
.bottom {
border: solid 1px #00FF00;
width: 100px;
}
.middle {
height: 100px;
width: 100px;
background: #FF0000;
margin-top: 10px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="parent">
<div class="head">隐藏元素上部</div>
<button id="middle" class="middle"></button>
<div class="bottom">隐藏元素底部</div>
</div>
</body>
</html>
display:none
display属性主要是用来改变元素的的显示方式,也就是通过改变元素显示角色来改变页面布局。
浏览器渲染结果
可见渲染树中已经隐藏了中间的红色元素,而且渲染树中已经没有了该元素的空间布局存在了,同时该元素无法响应点击事件。
html代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" >
<title>元素可见性测试</title>
<style>
.parent {
border: solid 1px #000000;
padding: 5px;
position: absolute;
top: 100px;
left: 100px;
}
.head {
border: solid 1px #0000FF;
width: 100px;
}
.bottom {
border: solid 1px #00FF00;
width: 100px;
}
.middle {
height: 100px;
width: 100px;
background: #FF0000;
margin-top: 10px;
margin-bottom: 10px;
display: none;
}
</style>
</head>
<body>
<div class="parent">
<div class="head">隐藏元素上部</div>
<button id="middle" class="middle" onclick="alert('click me!')"></button>
<div class="bottom">隐藏元素底部</div>
</div>
</body>
</html>
visibility:hidden
visibility属性可以控制整个元素的可见性。当元素处于不可见状态时,元素还是会影响文档的布局,占用和正常显示时相同大小的空间。
浏览器渲染结果
可见渲染树中没有显示红色部分,但是渲染树中仍然存在该元素所占用的空间。可是点击所在区域,该元素仍然无法响应点击事件。
html代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" >
<title>元素可见性测试</title>
<style>
.parent {
border: solid 1px #000000;
padding: 5px;
position: absolute;
top: 100px;
left: 100px;
}
.head {
border: solid 1px #0000FF;
width: 100px;
}
.bottom {
border: solid 1px #00FF00;
width: 100px;
}
.middle {
height: 100px;
width: 100px;
background: #FF0000;
margin-top: 10px;
margin-bottom: 10px;
visibility: hidden;
}
</style>
</head>
<body>
<div class="parent">
<div class="head">隐藏元素上部</div>
<button id="middle" class="middle" onclick="alert('click me!')"></button>
<div class="bottom">隐藏元素底部</div>
</div>
</body>
</html>
opacity:0
opacity属性是设置元素的透明度,当透明度为0,也就表示该元素不可见。所以,该属性不会影响到元素的空间布局。 空间布局和visibility:hidden相同,但是点击所属区域,会响应点击事件。
总结
- display:none 将元素从渲染树中移除,令元素不可见,同时不响应DOM事件。当要显示该元素时,需要重新设置该属性,浏览器重现显示该元素涉及到重排和重绘操作,比较耗费性能
- visibiliy:hidden 渲染树中保留了该元素的空间位置,但是元素不可见,同时不响应DOM事件。当要显示该元素时,由于元素布局没有改变,因此只涉及到重绘操作,耗费性能小于display:none
- opacity:0 渲染树中保留了该元素的空间位置,虽然元素不可见(透明了),但是会响应DOM事件。当要显示该元素时,性能代价比较类似与visibility:hidden