以前,我们已经看到如何使用CSS :focus
和:focus-visible
伪级在焦点模式下样式元素,以提高可访问性。如果我们想在父母的孩子聚焦并在拥挤的页面上为用户的可见度更加出色时,该怎么样,该怎么办?我们有什么选择?
让我们在本文中找出答案,从:focus-within
伪级开始。
表中的内容
- Table of Content
- Using :focus-within pseudo-class
- Using :has() pseudo-class for focus within
- When to use :focus-within and :has(:focus)?
- Summary
使用:焦点 - 伪级
虽然:focus
pseudo-class用于在焦点模式下选择一个元素时,:focus-within
用于在dom树中选择该元素的祖先。简而言之,:focus-within
将匹配其嵌套元素之一的任何元素(匹配:focus
)。
让我们看一个搜索框的示例,其中我们有两个层次的嵌套。第一级是带有search-container
类的div
,第二个是label
元素。
<div class="search-container">
<label>
Search a title
<input
type="text"
placeholder="Search"
id="search-box"
/>
</label>
<div>
<button class="clear-btn">Clear</button>
<button class="search-btn">Search</button>
</div>
</div>
然后,我们将search-container
类添加到顶级div
的:focus-within
,并在label
元素的:focus-within
中添加一些大纲,如下:
.search-container:focus-within {
outline: 2px solid rgba(66, 153, 225, 0.5);
outline-offset: 5px;
}
label:focus-within {
font-weight: 600;
}
这样,当我们专注于label
中的input
元素时,标签文本变为粗体,并且具有search-container
类的顶级div
的轮廓变得可见。当我们专注于按钮时,通过单击它们或使用Tab键,我们将看到只有带有class search-container
的顶级div
改变了其轮廓样式:
要调试:focus-within
的样式,我们可以前往DevTools,检查所需的元素并切换元素的:focus-within
状态,该元素在Styles
Tab -:hov
部分下列出。我们还可以按照相同的方法切换孩子的:focus
状态,并查看父母的样式如何变化:
现在我们了解了:focus-within
伪级,让我们看看我们是否可以使用:has()
pseudo-class实现相同的结果。
使用:has()伪级用于焦点
:has()
是一个功能性伪级,接受相对选择器作为输入的列表。如果该元素有一个孩子(或后代),它允许我们选择和样式元素,该元素使用以下语法匹配给定的选择器列表:
:has(<selectors-list>) {
/* styles */
}
例如,使用我们以前的搜索框,我们希望使用class search-container
的顶级div
样式,如果它具有与以下条件相匹配的子元素:
- 孩子有一个班级名称,
clear-btn
和 - 孩子是焦点模式
我们可以使用:has()
伪级来完成上述任务,如下所示:
.search-container:has(.clear-btn:focus) {
outline: 2px solid rgba(66, 153, 225, 0.5);
outline-offset: 5px;
}
,仅此而已。现在,只有当我们专注于Clear
按钮时,我们才能看到带有class search-container
的顶级div
更改其轮廓样式,而其余元素的样式未触及:
此外,我们还可以将多个选择器传递到:has()
伪级,例如针对Clear
按钮和Search
按钮的焦点状态:
.search-container:has(.clear-btn:focus, .search-btn:focus) {
outline: 2px solid rgba(66, 153, 225, 0.5);
outline-offset: 5px;
}
太好了。到目前为止,我们已经看到了如何使用:focus-within
和:has()
伪级的孩子的焦点状态设计父元素。这是一个问题,我们应该使用哪一个以及何时?
何时使用:focus-within and:has(:focus)?
在其一个孩子处于焦点中时,造型父元素可以显着提高:focus
和:focus-within
之外的可见度。当在一长串组件中使用键盘(例如产品卡,文章等列表)导航时,为父元素添加额外的样式可以帮助用户快速识别集中的部分及其容器,从而更好地了解上下文。
通常,使用:focus-within
伪级是完成上述任务的最直接方法。但是,:focus-within
匹配的焦点状态 ,这意味着,如果我们在焦点模式下有多个后代,祖先也将改变其样式。这并不总是理想的行为。
以我们的搜索框为例。当搜索输入焦点时,我们可能只想突出显示搜索框的标签,而不会在顶级div
中添加任何额外的样式。当两个按钮之一 clear 和搜索是焦点时,我们突出显示了容器div
。只有:focus-within
,实现这两种情况是不可能的。
在这种情况下,在特定容器上使用:has(:focus)
或在:has()
中添加明确的选择器(例如:has(#search-box:focus)
)可以是一个更好的解决方案。
但是,这里有一个性能。根据相对选择器传递给它的复杂程度,:has()
可能会昂贵,因为CSS引擎需要查询所有匹配元素以进行样式计算。通常,:focus-within()
比:has(:focus)
快,尽管差异可能并不重要。以下是列表中添加到同一元素li
时,这是两个伪级的性能测试的屏幕截图:
- 使用
:focus-within
伪级
- 使用
:has(:focus)
伪级
尽管上述测试中的性能差异可能并不显着,但是当我们具有复杂的DOM结构以及是否需要指定儿童的重点状态或常规“抓住它们”时,值得一下。 像:focus-within
一样。
最后,Firefox中不支持:has()
功能性伪级,因此您可能需要使用:focus-within
或添加后备。
概括
在本文中,我们学会了如何使用两个伪级:focus-within
和:has()
,以基于孩子的重点状态为父元素设计。我们还看到了它们之间的区别,何时可以比另一个更合适的选择。虽然可访问性影响有时可能是微妙而不明显的,例如直接焦点样式,但要增加对父元素的可见性,就像内部具有交互式组件的列表项目一样,始终是一个很好的考虑因素。使用键盘导航的用户将感谢您。
ð通过我的新书Learning Vue了解Vue。早期版本现在可以使用!
ð如果您想赶上我有时候,请在Twitter上关注我| Facebook | Threads。
喜欢这篇文章还是发现它有帮助?分享ðð¼ð