如何隐藏DOM元素

早在2011年整理了一篇有关于图片替换文本的方法,而前几天看到一篇有关于隐藏DOM元素的几种方法。今天这里也将继续说说如何隐藏DOM元素?

隐藏DOM元素方法

在《用 CSS 隐藏页面元素的 5 种方法》一文中介绍了五种方法隐藏DOM元素,并且剖析了它们之间的差异。这里也再回顾一下,在CSS中,要隐藏DOM元素常见的方法有:

  • 设置元素的opacity值为0
  • 设置元素的visibility值为hidden
  • 设置元素的display值为none
  • 设置元素的position值为absolute,并且将其移到不可见区域
  • 设置元素clip(在新的CSS中使用clip-path来替代clip

除此之外,还可以使用:

  • 设置元素的hidden

上面隐藏元素的方法都是大家常见的,也是众所周之的。当然除此之外还有一些特殊的小技巧,比如说:

  • 将元素的font-sizeline-heightwidthheight设置为0
  • 设置元素的transformtranslateX或者translateY的值为-100%

当然,或许在你的实战经验当中,你还有别的方案。对于其他的方案,我们不再罗列,咱们具体来看看各种隐藏DOM元素的差异。

隐藏DOM元素的差异性

上面简单的罗列了八种隐藏DOM元素的方式,其实给我们视觉上的效果,这些方法都可以让元素不可见(也就是我们所说的隐藏)。然而,屏幕并不是唯一的输出机制,比如说,屏幕上看不见的元素(隐藏的元素),但其中一些隐藏元素的方式在屏幕阅读器中并没有隐藏,它依然能被屏幕阅读器读出来(因为屏幕阅读器依赖于可访问性树来阐述)。为了消除它们之间的歧意,我们将使用以下条款:

  • 完全隐藏:元素既不在屏幕上可见,而且也不暴露在可访问性树上
  • 语义上隐藏:元素在屏幕上呈现,但不暴露在可访问性树上
  • 视觉上隐藏:元素没有在屏幕上呈现,但是暴露在可访问性树上

三种类型的隐藏总结下来如下表所示:

可见性状态 屏幕上 可访问性树
完全隐藏 隐藏 隐藏
语义上隐藏 可见 隐藏
视觉上隐藏 隐藏 可见

如何完全隐藏元素

针对上面所列的隐藏元素方式当中,能完全隐藏元素的方法有三种:

  • 通过CSS设置元素的display属性值为none
  • 通过CSS设置元素的visibility属性值为hidden
  • 通过HTML5元素的属性值hidden(就是给元素声明一个hidden属性值),比如<div hidden>

虽然上面的几种方法得到的结果相同,即内容在屏幕上不可见,屏幕阅读器也无法读到(不在可访问性树上),但它们之间还是有所差别的。

给DOM元素设置display:none;来隐藏元素,将导致元素完全消失,而且不会占据任何的空间。如果通过visibility:hidden;隐藏元素,元素虽然消失了,但会占据空间(其占据的空间和元素的大小有直接关系)。

除此之外,通过元素嵌套的方式,外部元素虽然设置了visibility:hidden并不能隐藏内部元素设置了visibility:visible的元素,如下所示:

<div style="visibility: hidden">
  <span>not visible</span>
  <span style="visibility: visible">visible!</span>
</div>

效果如下图所示:

如何完全隐藏元素

提示:除非非常明确知道嵌套的内容需要做什么,否则应该尽量的避免使用visibility: visible;,应该在CSS样式表中使用visibility:inherit;来替代。在默认情况之下,通过继承元素的visibility的值,就可以确保避免父元素显式设置了visibility:hidden;还让嵌套的元素偶然变得可见。

另外HTML5的hidden属性提供了一个很方便的API,只需要设置hidden = true可以切换元素是否可见。通过这种方式,元素本身并不会直接隐藏,但浏览器内部会解析成:

[hidden] {
  display: none;
}

这样一来,元素间接通过display:none;隐藏。

如何完全隐藏元素

虽然无法直接通过设置hidden来让元素可见,但可以通过CSS样式设置可让元素可见:

div[hidden] {
  display: block;
  visibility: hidden;
}

通过上面CSS设置,虽然div元素设置了hidden属性,元素不可见,但其表现形式类似于visibility:hidden;,具有一定的空间,除此之外,如果改变visibility的值为visible,元素虽然设置了hidden值,也可以让元素可见:

div[hidden] {
  display: block;
  visibility: visible;
}

如何完全隐藏元素

遗憾的是没法直接使用inheritinitial或者unset取消display:none;。另外initialunset会翻译成display:inline;,而inherit只是导入父元素的display的值。不过从上面的内容来看,我们可以使用扩展选择器来解决这种现象:

div[hidden] {
  display: block;
  /* ... */
}
div[hidden] {
  visibility: hidden;
}

如何语义上隐藏元素

语义上隐藏元素,指的是可访问性树上隐藏,但屏幕上会显示。其实这种隐藏,并未达到元素实际隐藏,因为其在屏幕上仍然是可见的,但其在屏幕阅读器上是不可读的。我们可以在元素上设置aria-hidden="true"来达到语义上隐藏元素。例如:

<a href="https://google.com">
  <img src="search-symbol.png" alt="" aria-hidden="true">
  Google Search
</a>

上面这种完全只是达到美化的效果。

提示:我们不应该在CSS的选择器[aria-hidden="true"]上添加隐藏元素的样式,比如visibility:hidden或者display:none。因为我们的目的很单纯,仅仅只是让屏幕阅读器无法阅读到。

注意:如果需要在屏幕上让元素不可见,仅仅在DOM元素上显示设置[aria-hidden="true"]是无法隐藏元素。而需要另外配合visibility:hidden或者display:none来达到所需要的效果。

有关于WAI-ARIA(Web Accessibility Initiative - Accessible Rich Internet Applications)更详细的介绍,可以阅读早前整理过的《WAI-ARIA 无障碍Web规范》文章,里面详细介绍了如何在HTML中使用ARIA。或者可以通过accessibility.voxmedia.com网站查阅HTML对应元素中ARIA如何使用。

如何语义上隐藏元素

另外在这个微博中将不间断的会更新关于WAI-ARIA相关的资料

如何视觉上隐藏元素

为了让Web页面更具有可读性,可访问性。隐藏DOM元素更应该采用的是视觉上隐藏元素,而在可访问性树上并不对元素进行隐藏。简单点说,在屏幕上不可见元素,但屏幕阅读器可见。从上述隐藏DOM元素的方式方法主要有:

  • 设置元素的opacity值为0
  • 设置元素的position值为absolute,并且将其移到不可见区域
  • 设置元素clip(在新的CSS中使用clip-path来替代clip
  • 将元素的font-sizeline-heightwidthheight设置为0
  • 设置元素的transformtranslateX或者translateY的值为-100%

虽然上述的方法都能对DOM元素进行隐藏,但其表现形式也是略有不同。

  • 通过CSS给元素设置opacity:0,让元素不可见,但其可具有一定的空间
  • 通过CSS给元素设置transformtranslateX或者translateY的值为-100%,元素不可见,但其也具有一定的空间

如何视觉上隐藏元素

设置元素的position值为absolute,并且将其移到不可见区域。这种方法虽然隐藏元素,但元素也会脱离文档流,在Web显示中不占据空间。

为什么会如此,请阅读有关于position相关的介绍:《十步图解CSS的position》和《你对Position的了解程度有多少?》。

另外使用CSS的clip(或者新属性clip-path)和设置元素的font-sizeline-heightwidthheight0也可以隐藏元素,虽然它们没有将元素移除到不可见区域,但这两种方法将元素的大小变成为了0。造成不可见现象。

HTML5 Boilerplate中采用的就是这种方式:

.visuallyhidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  border: 0;
  padding: 0;
  clip: rect(0 0 0 0);
  overflow: hidden;
}

要让clip生效,必须给元素的position的值设置为absolute或者fixed,有关于这方面的详细介绍,可以阅读《Clip》一文。不过在CSS规范中已经开始使用clip-path属性来替代clip属性,简单点说,可以使用clip-path:inset(100%)来替代clip:rect(0 0 0 0)

有关于clip-path相关的介绍可以阅读《理解Clip Path》和《CSS的clip-path》。

但很多时候想让.visuallyhidden元素在:focus或者:active可见,可以在.visuallyhidden元素上动态添加.focusable(比如click事件给元素添加此类名):

.visuallyhidden.focusable:active,
.visuallyhidden.focusable:focus {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  clip: auto;
  overflow: visible;
}

当然,针对于优秀的现代浏览器,可以不借助JavaScript事件,直接使用CSS3的:not()选择器来更新.visuallyhidden样式:

.visuallyhidden:not(:focus):not(:active) {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  border: 0;
  padding: 0;
  clip-path: inset(100%);
  clip: rect(0 0 0 0);
  overflow: hidden;
}

总结

文章详细介绍了如何隐藏DOM元素的方法。也简单的对各种隐藏元素方式做了对比,最后简单的回顾一下:

  • 通过HTML5的API,可以在元素上显式声明hidden,直接隐藏元素
  • 使用aria-hidden="true从可访问性树上隐藏元素,但对于用户而言,在屏幕上仍然可见,只是屏幕阅读器无法阅读
  • 使用.visuallyhidden声明隐藏CSS的样式,在屏幕上隐藏元素
  • 使用visibility:inherit替代visibility:visible避免意外地显示内容
  • 对于设置了aria-hidden的元素,不附加任何隐藏CSS隐藏元素的样式

对比下来,为了让你的Web页面变得更具可访问性,可阅读性,我们更趋向于使用.visuallyhidden配合clip(或者clip-path),当然也可以是其它只在屏幕上隐藏而在可访问性树上不隐藏的CSS样式。只不更常见的是clip方式而以。

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:http://www.w3cplus.com/css/hidden-dom-element.html

返回顶部