如果用文字来描述,简单一句话就是display:none的元素是彻底消失,也就是说该元素的宽度、高度等各种属性值都将“丢失”,不在文档流中占位,浏览器也不会解析该元素;而visibility:hidden只是视觉上消失了,可以理解为透明度为0(opacity:0)的效果,它仍具有高度、宽度等属性值,因此在文档流中占位,浏览器会解析该元素。
因此,我们可以知道display:none的元素隐藏后不占据额外空间,状态切换会产生回流和重绘,而visibility:hidden的元素虽然隐藏了,但它们仍然占据着空间,它的状态切换只会引起页面重绘。(关于回流与重绘见下文)
举个栗子:
<style>
div {
width: 200px;
height: 200px;
background: #ccc;
margin-top: 10px;
}
.div1 {
display: none;
}
.div2 {
visibility: hidden;
}
</style>
<body>
<div class="div1">
<p>display:none</p>
</div>
<div class="div2">
<p>visibility:visible</p>
</div>
</body>
在浏览器中打开控制台。我们可以看到如图,虽然两个div都并不可见,但div1没有占据物理空间,而div2却占有原本的物理空间。 div1:
div2:
当页面中的一部分元素需要改变规模尺寸、布局、显示隐藏等,页面重新构建,此时就是回流。所有页面第一次加载时需要产生一次回流。 可以参考博文: 页面重绘和回流以及优化 浏览器的渲染过程及优化
display:none虽然不会被子元素继承,但是因为父元素都不在了,子元素自然也就不会显示了。
visibility:hidden会被子元素继承,可以通过设置子元素visibility:visible 使子元素显示出来
还是举个栗子:
<style>
.div1,.div2 {
width: 200px;
height: 200px;
background: #ccc;
margin-top: 10px;
}
.div11,.div22 {
width: 100px;
height: 100px;
background: #ff0000;
margin-top: 10px;
}
.div1 {
display: none;
}
.div2 {
visibility: hidden;
}
</style>
<body>
<div class="div1">
<div class="div11">
<p>div11</p>
</div>
<p>div1</p>
</div>
<div class="div2">
<div class="div22">
<p>div22</p>
</div>
<p>div2</p>
</div>
</body>
如图,我们可以看到div11的dispaly属性为block,并未继承父级div1的display:none,但因为div1不占有物理空间,所以div11仍不占有物理空间。但div22却继承了div2的visibility:hidden。 div11:
div22:
我们更改代码如下:
<style>
.div1,
.div2 {
width: 200px;
height: 200px;
background: #ccc;
margin-top: 10px;
}
.div11,
.div22 {
width: 100px;
height: 100px;
background: #ff0000;
margin-top: 10px;
}
.div1 {
display: none;
}
.div11 {
display: block;
}
.div2 {
visibility: hidden;
}
.div22 {
visibility: visible;
}
</style>
<body>
<div class="div1">
<div class="div11">
<p>div11</p>
</div>
<p>div1</p>
</div>
<div class="div2">
<div class="div22">
<p>div22</p>
</div>
<p>div2</p>
</div>
</body>
如图发现div11仍不可见且不占有物理空间,而div22已经显示出来。
display:none 的元素都已经不再页面存在了,因此肯定也无法触发它上面绑定的事件;
visibility:hidden 元素上绑定的事件也无法触发;
transition对于display肯定是无效的,大家应该都知道;
transition对于visibility也是无效的;