为了更好的可访问性,使用clip隐藏内容

我们需要在创建一个整洁、简单的视觉设计和提供可访问的内容和功能之间做平衡。一个通用的解决办法是向屏幕阅读器提供补充文本,并通过CSS隐藏这些文本。请访问我们的屏幕阅读器测试:无障碍隐藏内容方案来了解更多关于隐藏内容的可访问性的信息。

从Jonathan的这篇博文 Adaptive Themes中的评论和其他地方的提问来看,许多开发者仍然对这个问题感到困惑。因此,首先扼要重述一下基本的声明,当提及隐藏内容时:

使内容对辅助技术(AT)可访问的技术

position:absolute;
clip:rect(1px 1px 1px 1px);
position:absolute; left:-999em;
position:absolute; top:-999em;
text-indent:-999em;

使内容无法访问的技术(所有用户均不可见)

visibility:hidden; /* in most screen readers*/
display:none;
/*in most screen readers and with some exceptions
http://juicystudio.com/article/screen-readers-display-none.php*/
overflow:hidden;
height:0; /* In VoiceOver */

补充说明一下,在使用上面最后一条规则时,如果 Voice Over忽略了内容,这不是 因为height:0(通常都是这样认为),而是由于overflow:hidden,这是说的通的,因为0 × 0像素的盒子不能隐藏内容。

技术与挑战

您可以查看Hiding Content for Accessibility,这篇文章总结了不同的技术及其陷阱,但总之,每种方法都要解决下面这些共同问题:

  • 它应使元素消失(仿佛文档中不存在该元素):这意味着应该没有多余的空白、没有滚动条、不能出现与层叠相关的问题(不可点击)等。
  • 当隐藏容器中的元素获得焦点时,应防止出现意外的滚动。 也就是说,当用户使用tab导航到隐藏容器内的可聚焦的元素时,网页不应该跳跃。
  • 双向(bidi)字符集语言友好。 即该技术应该同时支持从右到左,从左到右的界面,如阿拉伯文和希伯来文。

注:检测屏幕阅读器能否访问你隐藏的内容的一种简单的方法,就是使用键盘来访问隐藏容器内的可聚焦元素(可以在容器中添加一条链接)。如果键盘导航能够跳至隐藏容器内的元素,那么内容是可以访问的 。

最好的方法(理论上)

以我的愚见,迄今为止最好的方法– 是 Jeff Burnz 的clip technique 。很简短,并且与方向无关。就是这样:

.element-invisible {
    position: absolute !important;
    clip: rect(1px 1px 1px 1px);  /* IE6, IE7 */
    clip: rect(1px, 1px, 1px, 1px);
}

注意,所有的浏览器都理解第一条clip的声明,但IE6和7不能理解第二个正确的语法(逗号分隔值,标准中使用的方法)。

不幸的是,Webkit、Opera以及IE(在一定程度上)使用这种方法会产生问题。会产生不必要的滚动条,取决于隐藏元素的布局和/或在页面上的位置。总之,这些浏览器可以剪切盒子,但其行为就好像被剪切的元素保持了其原有的布局。注意虽然盒子真的被裁切了,即使在页面上好像仍然占有空间,但它不干扰周围的元素。

这种行为与规范不符 : 已被裁剪的内容不会溢出( Content that has been clipped does not cause overflow) 。如果有人知道答案,请留言。

方案二

Jonathan Snook 和他雅虎的同事想出了解决WebKit /Opera下问题的一个方案。它结合了两种技术:

.element-invisible {
  position: absolute !important;
  height: 1px;
  width: 1px;
  overflow: hidden;
  clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  clip: rect(1px, 1px, 1px, 1px);
}

如果我们能够依靠clip的话 ,这已经很好了,但我们不能。请记住clip和overflow之间的主要区别是,它们针对的盒子不一样。一个是边界框(border box ),而另一个是内容框(content box )。上面的规则可以有效地“抹掉”边框和内边距(内容框外边缘),但不能在大多数浏览器中防止滚动条。

所以,更“保险”的规则是:

.element-invisible {
  position: absolute !important;
  clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  clip: rect(1px, 1px, 1px, 1px);
  padding:0 !important;
  border:0 !important;
  height: 1px !important;
  width: 1px !important;
  overflow: hidden;
}

它看起来不好看,但它能够防止与盒模型相关的的问题。我写的声明使用了一个特定的顺序,如果有一天clip的效果与人们期望的一致,那么我们就可以去掉clip后面的所有声明,只使用:

.element-invisible {
  position: absolute !important;
  clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  clip: rect(1px, 1px, 1px, 1px);
}

Tab键导航

这个“问题”是关于明眼键盘用户的。如果隐藏的内容是垂直偏移( 即position:absolute; top:-999em;),那么Tab键跳到隐藏容器内的可聚焦元素时,页面会出现滚动。在任何情况下,即使没有偏移(即position:absolute; left:-999em;,其行为也是混乱的,因为没有视觉线索告诉这些用户他们在页面的哪个位置。

我们可以尝试为使用指点设备和键盘来导航的人“修复”这个问题,但这可能并不奏效。我们的想法是使用伪类 :hover把隐藏容器中的可聚焦元素从Tab键序列中移除。例如,使用这样的规则:

body:hover .element-invisible a,
body:hover .element-invisible input,
body:hover .element-invisible button {
  display: none;
}

只要用户把鼠标光标放在页面上,上面的规则可以把链接和表单控件从Tab键顺序中删除了(请注意,此规则在IE7下可能会造成性能问题)。

类名的语义

我不肯定类名中使用element是否有语义(如element-hidden )。好像有点冗余,一个选择符总是与元素相匹配的。我更倾向于使用html5boilerplate的方法,他们使用visuallyhidden,这里我使用连字符:

.visually-hidden {
  position: absolute !important;
  clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  clip: rect(1px, 1px, 1px, 1px);
  padding:0 !important;
  border:0 !important;
  height: 1px !important;
  width: 1px !important;
  overflow: hidden;
}
body:hover .visually-hidden a,
body:hover .visually-hidden input,
body:hover .visually-hidden button {
  display: none !important;
}

使内容不可访问

如果你的目标是向所有的用户隐藏内容,按照Webaim的建议同时使用visibility和display

.hidden {
  visibility: hidden;
  display: none;
}

这是2007年的建议,如果谁有更好的方法,请留言。

《为了更好的可访问性,使用clip隐藏内容》有2个想法

  1. /* Hide only visually, but have it available for screenreaders: h5bp.com/v */
    .visuallyhidden {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
    }

    /* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: h5bp.com/p */
    .visuallyhidden.focusable:active,
    .visuallyhidden.focusable:focus {
    clip: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    position: static;
    width: auto;
    }

发表评论