Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[译]如何隐藏DOM元素? #142

Open
FrankKai opened this issue Apr 23, 2019 · 6 comments
Open

[译]如何隐藏DOM元素? #142

FrankKai opened this issue Apr 23, 2019 · 6 comments
Labels

Comments

@FrankKai
Copy link
Owner

原文链接:https://allyjs.io/tutorials/hiding-elements.html

@FrankKai
Copy link
Owner Author

FrankKai commented Apr 23, 2019

隐藏 DOM 元素

这篇文章的主要解释了多种隐藏DOM元素的实现方式。

当我们谈到一个元素被隐藏(hidden)时,我们通常是理解成不可见(not visible)。
然而,显示器不是唯一的应用隐藏内容的地方。电子阅读器和盲文显示器等系统依赖于accessibility树中的文档实现。

为了消除歧义,我们将进行以下的术语约定:

  • 完全隐藏(Completely hidden)
    元素在屏幕上未渲染,在无障碍(accessibility)树中也不暴露,通过键盘获取不到访问权限。

  • 语义上的隐藏(Semantically hidden)
    元素在屏幕上渲染,在无障碍树中不暴露,通过键盘可以获取到访问权限。

  • 视觉上的隐藏(Visually hidden)
    元素在屏幕上未渲染,在无障碍树上暴露,通过键盘获取到访问权限。

通过以下表格可以很明确的对比出三种隐藏方式的异同:

visibility state on screen in accessibility tree keyboard navigation
completely hidden hidden hidden not navigatable
semantically hidden visible hidden navigatable
visually hidden hidden visible navigatable

无障碍树是什么?

  • 无障碍树(通常简写为"AT"),AT也是“Assistive Technology”的缩写。
  • 无障碍树是一个对象结构,它就像DOM一样,但是有特殊的用途和目的。
  • AT对于web应用来说是不可见的,它来自于DOM。
  • 在某种程度上,AT是DOM的视图,仅显示语义上重要的结构。

@FrankKai
Copy link
Owner Author

FrankKai commented Apr 23, 2019

如何完全隐藏元素

完全隐藏一个元素有以下3种方式:

  • 通过CSS属性display,例如:display: none;
  • 通过CSS属性visibility,例如:visibility: hidden;
  • 通过HTML5属性hidden,例如:<span hidden>

以上3种方式都会有相同的效果,内容不会被渲染也不会暴露在无障碍树中,他们有不同的表现效果。

CSS属性displayvisibility

display:none;会导致元素完全消失,它不会占用任何空间,也不是animatable的。
visibility:hidden;允许动画并且保留元素在屏幕上的占用空间,会留一个blank(一个空白区域)。可以通过visibility:visible去显示嵌套的内容:

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

提醒:尽量不要用visibility: visible;去显示一个嵌套的子元素,会导致父元素设置hidden失效。

HTML5的hidden属性

HTML5的hidden属性是一个很方便的API,可以很方便的通过element.hidden=true;控制元素的显示或控制。元素自己不会隐藏内容,但是浏览器内部的样式表会包含以下的CSS规则:

[hidden] {
    display: none;
}

安全地重写hidden属性

我们千万不要恢复hidden属性的隐藏效果。然而,可以交换display以查看visibility,例如我们可以通过以下方式使得元素可动画:

.my-element[hidden] {
  display: block;
  visibility: hidden;
}

但是我们不能用inherit,initial或者unset去撤销display:none;initial和unset将会转换成display:inline,inherit会继承父元素的属性。我们可以使用扩展选择器去解决重复定义的问题:

.my-element,
.my-element[hidden] {
  display: block;
  /* ... */
}
.my-element[hidden] {
  visibility: hidden;
}

@FrankKai
Copy link
Owner Author

FrankKai commented Apr 23, 2019

如何语义上隐藏元素

为了将内容从无障碍树上隐藏,但是在屏幕上保留,我们可以使用属性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;,因为这会导致失去仅从屏幕阅读器上隐藏元素的能力。

@FrankKai
Copy link
Owner Author

FrankKai commented Apr 23, 2019

如何从视觉层面隐藏元素

为了确保使无障碍树的当前结构生效,我们也许需要提供不可见的内容。下面的CSS来自HTML-bp,这是基于无障碍隐藏元素的。

.visuallyhidden {
  position: absolute;

  width: 1px;
  height: 1px;
  margin: -1px;
  border: 0;
  padding: 0;

  clip: rect(0 0 0 0);
  overflow: hidden;
}

CSS属性clip在任何浏览器都是被支持的,但是在CSS Masking 1中被弃用。取而代之的,我们建议使用clip-path,它还没有被广泛支持。所以会用clip-path:inset(100%)去覆盖clip:rect(0 0 0 0)样式。

当Internet Explorer 9 - 11使溢出的容器focusable,clip确保绘制的outline,:focus不可见,并且无法单击该元素。

说到可聚焦元素,我们可能会使用.visuallyhidden样式进行跳过链接,在这种情况下,我们需要一种方法来撤消视觉隐藏。 HTML5 Boilerplate为此提供了以下样式:

.visuallyhidden.focusable:active,
.visuallyhidden.focusable:focus {
  position: static;

  width: auto;
  height: auto;
  margin: 0;

  clip: auto;
  overflow: visible;
}

但是,这种方法会带来一些问题。首先,我们需要通过添加可聚类类来声明元素兼容。第二,更重要的是 ,我们将样式重置为可能不是我们想要渲染的值。相反,我们可以使用:not(),这在每个现代浏览器中都受支持。 根据Beware推出的屏幕外可访问文本,上面的CSS片段可能会给某些屏幕阅读器带来问题。似乎(在某些情况下)单独的单词可能会被连接起来,因此很奇怪。幸运的是,我们可以通过添加white-space: nowrap来阻止空白的不希望的崩溃;。

2017版的.visuallyhidden

.visuallyhidden:not(:focus):not(:active) {
  position: absolute;

  width: 1px;
  height: 1px;
  margin: -1px;
  border: 0;
  padding: 0;

  white-space: nowrap;

  clip-path: inset(100%);
  clip: rect(0 0 0 0);
  overflow: hidden;
}
  • 浏览器支持性好,兼容IE9-11。
  • 它侧重于为可聚焦元素(如跳过链接)重新设置所有内容。
  • 它是已经弃用的clip属性的替代。

@FrankKai
Copy link
Owner Author

Keyboard navigation

仅在视觉上和语义上隐藏的元素需要注意。类似<a href="...">的focusable element保持键盘可导航,即使元素在屏幕上不可见或者在无障碍树上不可见。

为了确保有视力的键盘用户不会最终聚焦他们看不到的元素,并且视力障碍用户没有聚焦那些不存在的元素,我们需要确保部分隐藏的内容,不能通过Tab以及Shift Tab键访问到。我们可以通过添加tabindex="-1"给元素从而做到键盘不可导航。

@FrankKai
Copy link
Owner Author

总结

  • 使用hidden属性完全隐藏元素
  • 使用aira-hidden属性隐藏无障碍树上的元素
  • 使用.visuallyhidden类隐藏屏幕上的一个元素
  • 使用visibility: inherit;替代visibility:visible;从而避免事故性得展示内容
  • 不要为添加了aria-hidden的元素附加任何样式
  • 通过添加tabindex=“-1”,使得屏幕不可见,无障碍树不暴露的元素,同时做到键盘不可访问

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant