保持父元素在子元素获得 :focus 时可见

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

假设我们有一个 <div>

我们希望此 div 在悬停时可见,因此

div:hover { 
  opacity: 1; 
}

我们也需要焦点样式,以实现无障碍性,因此

div:hover,
div:focus { 
  opacity: 1; 
}

但是 div 本身无法获得焦点,因此我们需要

<div tabindex="0">
</div>

此 div 中包含内容。不仅是文本,还有链接。

<div tabindex="0">
  <p>This little piggy went to market.</p>
  <a href="#market">Go to market</a>
</div>

这就是事情变得棘手的地方。

一旦焦点从 div 移动到其内部的锚链接,div 就不再处于焦点状态,这会导致这种奇怪且可能令人困惑的情况

在此示例中,:hover 显示 div,包括其中的链接。聚焦 div 也有效,但一旦您按 Tab 键将焦点移动到链接,所有内容都会消失。内部的链接可以接收焦点,但由于 div 父元素在视觉上隐藏,因此它在视觉上是隐藏的

这里的一种解决方案是确保当其内部的任何内容获得焦点时,div 保持可见。新的 CSS 在这里为我们提供了支持

div:hover,
div:focus,
div:focus-within { 
  opacity: 1; 
}

GIF 工作

:focus-within 的浏览器支持不是很好。如果它完美无缺,这就是我们唯一需要的。事实上,我们甚至不需要 :focus,因为 :focus-within 也处理了这一点。

但在那之前,我们可能需要 JavaScript 来帮忙。您实际处理此问题的方法取决于具体情况,但思路大概如下…

  1. 当某个元素获得焦点时…
  2. 如果该元素的父元素也可聚焦,请确保它可见
  3. 当链接失去焦点时…
  4. 您为确保父元素可见所做的一切都将被反转

这里有很多需要考虑的事情,比如您实际上想要监视哪些元素、如何使它们可见以及您希望向上遍历树多远。

类似这样的方法是一种非常基本的方法

var link = document.querySelector(".deal-with-focus-with-javascript");

link.addEventListener("focus", function() {
  link.parentElement.classList.add("focus");
});
link.addEventListener("blur", function() {
  link.parentElement.classList.remove("focus");
});

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 :focus-within 有用的 a11y 技巧