本文参与了1024 程序员节活动,欢迎正在阅读的你也加入。
隐藏元素 display:none 与 visibility:hidden 的区别你真的知道吗?
有关隐藏元素的方式 display: none 与 visibility:hidden 的区别,这可以说是 css 面试题当中最常见的一道题了。相信大多数开发者被问到的第一答案就是:
display: none 不占据空间,visibility: hidden 占据空间。但实际上两者之间的区别并不只是不占据空间这么简单,且听我娓娓道来。
区别之一: visibility 拥有继承性
什么意思呢? 我们知道,如果一个元素的 visibility 设置为 hidden,它的子元素也会被隐藏,那么你知道子元素被隐藏的原理是什么吗?就是继承性。简单来说,就是子元素也继承了 visibility:hidden 的特性。换句话说,如果我们将子元素修改成 visibility: visible,你会发现子元素不再是隐藏,而是显示。来看一个例子感受一下:
html 代码如下:
<div class="vh-parent">
<div class="vh-inherit-child">这是继承子元素的hidden隐藏</div>
<div class="vv-child">子元素设置了visibility: visible之后又显示了</div>
</div>
css 代码如下:
.vh-parent {
visibility: hidden;
}
.vv-child {
visibility: visible;
}
实际运行效果如下图所示:
区别之二: visibility 不会影响 css 计数器
visibility:hidden 不会影响计数器的计数,这和 display:none 完全不一样。举个例子,如下 CSS 和 HTML 代码:
<ol>
<li>列表</li>
<li class="dn">列表</li>
<li>列表</li>
<li>列表</li>
</ol>
<ol>
<li>列表</li>
<li class="vh">列表</li>
<li>列表</li>
<li>列表</li>
</ol>
.vh {
visibility: hidden;
}
.dn {
display: none;
}
ol {
border: 1px solid;
margin: 1em 0;
counter-reset: test;
}
li:after {
counter-increment: test;
content: counter(test);
}
实际运行效果如下图所示:
可以看到,visibility:hidden 虽然让其中一个列表不可见了,但是其计数效果依然存在。相比之下,设置 display:none 的列表就完全没有参与计数运算。
区别之三: visibility 过渡效果有效,而 display 则无效
CSS3 transition 支持的 CSS 属性中有 visibility,但是并没有 display。如以下示例:
/* 过渡效果无效 */
.test {
display: none;
position: absolute;
opacity: 0;
transition: opacity 0.25s;
}
.test:hover {
display: block;
opacity: 1;
}
/* 过渡效果无效 */
.test {
position: absolute;
opacity: 0;
transition: opacity 0.25s;
visibility: hidden;
}
.test {
visibility: visible;
opacity: 1;
}
由于 transition 可以延时执行,因此,和 visibility 配合可以使用纯 CSS 实现 hover 延时显示效果,由此提升我们的交互体验。来看如下一个示例:
<table>
<tr>
<td>数据1</td>
<td>数据2</td>
<td>
<a href>操作▾</a>
<div class="list">
<a href>编辑</a>
<a href>删除</a>
</div>
</td>
</tr>
<tr>
<td>数据1</td>
<td>数据2</td>
<td>
<a href>操作▾</a>
<div class="list">
<a href>编辑</a>
<a href>删除</a>
</div>
</td>
</tr>
</table>
td {
padding: 5px 10px;
border: 0;
background: #fff;
font-size: 14px;
}
td a {
display: block;
}
.list {
width: 80px;
position: absolute;
visibility: hidden;
border: 1px solid #ccc;
background: #fff;
}
td:hover .list {
visibility: visible;
transition: visibility 0s 0.2s;
}
.list a {
padding: 5px 10px;
color: #333;
}
.list a:hover {
background-color: #f5f5f5;
}
效果如下图所示:
以上是一个很常见的 hover 悬浮显示列表效果,而且有多个触发点相邻,对于这种 hover 交互,如果在显示的时候增加一定的延时,可以避免不经意触碰导致覆盖目标元素的问题。如果没有增加延时效果,则会存在如下情况:我本来想去 hover 第二行的“操作”文字,但是由于鼠标光标移动路径不小心经过了第一行的“操作”,结果把第二行本来 hover 的“操作”覆盖了,必须重新移出去,避开干扰元素,重新 hover 才行。如此一来,对用户体验就不好了。而恰好 visibility 就可以处理这个问题。
区别之四: visibility 可以获得元素的尺寸位置,而 display 则无法获取
在实际开发中,我们会遇到这样的场景:我们需要对隐藏元素进行尺寸和位置的获取,以便对交互布局进行精准定位。这时候如果使用 display:none 来隐藏元素,我们获取到元素的尺寸位置则是 0,但是 visibility 则不会。js 代码如下:
console.log('clientWidth: ' + element.clientWidth);
console.log('clientHeight: ' + element.clientHeight);
console.log('clientLeft: ' + element.clientLeft);
console.log('clientTop: ' + element.clientTop);
console.dir(element.getBoundingClientRect());
因此面对以上的场景,我们更应该选择 visibility 来隐藏元素。
区别之五: visibility 在无障碍访问这一块比 display 更友好
视觉障碍用户对页面的状态变化都是通过声音而非视觉感知的,因此有必要告知其准确信息。
通过本文,我们了解到了 visibility 与 display 的详细区别,在面试的时候我们也不会只回答的片面了,知晓以上的区别能给我们的面试加分。
隐藏元素方式
最后分享一些隐藏元素的方式:
- 如果希望元素不可见,同时不占据空间,辅助设备无法访问,同时不渲染,可以使用
<script>
标签隐藏。例如:
<script type="text/html">
<img src="1.jpg" />
</script>
<script>
标签是不支持嵌套的,因此,如果希望在<script>
标签中再放置其他不渲染的模板内容,可以试试使用<textarea>
元素。例如:
<script type="text/html">
<img src="1.jpg" />
<textarea style="display:none;">
<img src="2.jpg">
</textarea
>
</script>
- 如果希望元素不可见,同时不占据空间,辅助设备无法访问,但资源有加载,DOM 可 访问,则可以直接使用 display:none 隐藏。例如:
.hidden {
display: none;
}
- 如果希望元素不可见,同时不占据空间,辅助设备无法访问,但显隐的时候可以有 transition 淡入淡出效果,则可以使用:
.hidden {
position: absolute;
visibility: hidden;
}
- 如果希望元素不可见,不能点击,辅助设备无法访问,但占据空间保留,则可以使用 visibility:hidden 隐藏。例如:
.hidden {
visibility: hidden;
}
- 如果希望元素不可见,不能点击,不占据空间,但键盘可访问,则可以使用 clip 剪裁隐藏。例如:
.clip {
position: absolute;
clip: rect(0 0 0 0);
}
.out {
position: relative;
left: -999em;
}
- 如果希望元素不可见,不能点击,但占据空间,且键盘可访问,则可以试试 relative 隐藏。例如,如果条件允许,也就是和层叠上下文之间存在设置了背景色的父元素,则也可以使用更友好的 z-index 负值隐藏。例如:
.lower {
position: relative;
z-index: -1;
}
- 如果希望元素不可见,但可以点击,而且不占据空间,则可以使用透明度。例如:
.opacity {
position: absolute;
opacity: 0;
filter: Alpha(opacity=0);
}
- 如果单纯希望元素看不见,但位置保留,依然可以点可以选,则直接让透明度为 0。例如:
.opacity {
opacity: 0;
filter: Alpha(opacity=0);
}
- 在标签受限的情况下希望隐藏某元素文字,例如:
.hidden {
text-indent: -120px;
}
- 如果希望显示的时候可以加一个 transition 动画,可以使用 max-height 进行隐藏。
.hidden {
max-height: 0;
overflow: hidden;
}
注: 以上内容阅读《css世界》而整理。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。