悬停状态下的选项卡可访问性

IT技术 css reactjs sass accessibility jsx
2021-05-20 22:35:31

我有一个组件,在悬停时,它会显示一个按钮和一个链接,您可以单击它。这不是菜单……只是页面中间的一个框。

对于可访问性,我希望用户能够使用 Tab 键进入容器(现在发生,并在.HiddenUntilHover类中显示内容),并且还可以继续 Tab 键切换到显示在悬停/聚焦状态下的按钮和链接。

现在您可以专注于容器并查看悬停状态;但是,当您使用 Tab 键时,它只会转到下一个元素,并且不允许您在悬停状态下使用 Tab 键切换到按钮或链接。

伪代码示例:

/* My component .jsx */
<div tabIndex="0" className="MainContainer">
 <div className="SomeOtherClass">
   <div className="HiddenUntilHover">
     /* I would like to be able to tab to these clickable things! */
     <button>Click me!</button>
     <a href="...">I am also clickable</a>
   </div>
 </div>
</div>

还有我的 SCSS:

.HiddenUntilHover {
  display: none;
}

MainContainer:focus,
MainContainer:hover,
> .HiddenUntilHover {
    display: block
}
4个回答

当框处于焦点时,进一步移至按钮将使框模糊,这将隐藏它及其内容,因此焦点将移动到下一个可访问的元素。我认为这就是您正在经历的行为。

您可能会考虑在框进入焦点时使用插入aria-activedescendanttabindex属性。这需要一点javascript。

严格来说,您不需要依赖悬停状态来使该控件可访问。可能有一个屏幕外(或剪辑)按钮/链接,它不是隐藏 ( display:none) 框的 DOM 子项如果您采用这种方法,请仔细阅读该aria-owns属性。

只要它被标记为按钮或链接(或具有tabindex="0"设置),并且不是“真正”隐藏,就应该可以使用 Tab 键访问它。

几天前我遇到了这个问题,我使用 css 类解决了这个问题,使悬停的内容可以通过键盘导航访问。

我让这个工作的方式是使用 css 伪类来确保当div元素处于活动状态并获得焦点时,里面的按钮也会显示。特别是额外使用:focus-within&:focus-visible应该确保当您在列表项上使用 Tab 键时,它们的内容也会显示出来并且可以通过键盘访问。

.MainContainer  {
  &:not(:hover, :focus, :active, :focus-visible, :focus-within) {
    .HiddenUntilHover {
      visibility: hidden;
    }
  }
}
<body>
    <div tabIndex="0" className="MainContainer">
        Content
        <div className="SomeOtherClass">
          <div className="HiddenUntilHover">
            <button>Click me!</button>
            <a href="...">I am also clickable</a>
          </div>
        </div>
      </div>
  </body>

是此工作Codesandbox 演示链接

例如,尝试增加类的属性MainContainer

.MainContainer {
  width: 100%;
  height: 100px;
}
.MainContainer .HiddenUntilHover {
  display: none;
}
.MainContainer:hover .HiddenUntilHover, .MainContainer:focus .HiddenUntilHover {
  display: block;
}

悬停时出现的元素本质上是不可访问的。您遇到了代码问题的一方面,难以通过键盘访问。但是想想没有真正的悬停概念的触摸屏:有什么方法可以到达智能手机或平板电脑上的按钮吗?

对于更务实的答案,如果您需要保持悬停,那么比已经发布的两个解决方案更简单的解决方案可能如下:使用 focusin 和 focusout 事件。例如,请参阅此问题以了解与焦点/模糊的解释和差异,以及此 w3school 文档以了解浏览器兼容性。您必须以不同的方式构建 HTML,例如:

<div id="outer">
<div id="hover">
...
</div><!--hover-->
<button>Your button which only appears on hover</utton>
</div><!--outer-->

以及使用一些js:

$('#outer').on('focusin', __=>$('#hover').classNames.add('keep-visible'));
$('#outer').on('focusout', __=>$('#hover').classNames.remove('keep-visible'));

使用相应的 .keep-visible 类将使元素 display:block (我不是 CSS 专家,我让您编写代码)。

整体功能如下:当其中的某个元素#outer获得焦点时,由于冒泡而触发 focusin 元素。在这种情况下,您将类 .keep-visible 放置在使元素保持可见的状态。当焦点离开 中的最后一个元素时会触发 focusout 事件#outer此时,您删除 .keep-visible 类,这会使元素消失。

根据上面的链接,onfocusin/out 不是标准的,但包括 IE 在内的所有主要浏览器都支持。Firefox 是最后一个在 52.0 中实现它的,所以它是一种事实上的标准;我们可以合理地预期它不会很快消失。