:focus-within
检测内部元素的焦点状态
什么是 :focus-within?
:focus-within 伪类用于选择自身或其后代元素获得焦点的元素。
这是一个非常实用的选择器,可以让我们在内部元素获得焦点时,改变父容器的样式。
与传统的 :focus 只能选择获得焦点的元素本身不同,
:focus-within 可以向上传播,让父元素也能响应内部元素的焦点状态。
这在表单设计、搜索框、对话框等场景中特别有用。
- 当元素自身或任何后代元素获得焦点时匹配
- 焦点状态向上传播到所有祖先元素
- 支持嵌套元素的焦点检测
- 无需 JavaScript 即可实现父容器响应
语法
/* 基础语法 */
element:focus-within {
/* 当 element 或其后代获得焦点时的样式 */
}
/* 实际应用示例 */
form:focus-within {
border-color: blue;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
/* 嵌套使用 */
.container:focus-within .label {
color: var(--primary);
font-weight: 600;
}
:focus-within- 专门用于焦点检测,性能更好,浏览器支持更早:has(:focus)- 更通用的父选择器,但性能稍差,浏览器支持较晚- 对于焦点检测场景,推荐使用
:focus-within
示例 1: 表单容器焦点效果
当表单内的任何输入框获得焦点时,整个表单容器会改变样式,提供清晰的视觉反馈。
/* 表单容器焦点样式 */
.focus-form:focus-within {
border-color: var(--primary);
background: var(--primary-light);
box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.1);
}
/* 标题响应焦点状态 */
.focus-form:focus-within h3 {
color: var(--primary);
}
/* 当前获得焦点的输入框的标签高亮 */
.form-group:focus-within label {
color: var(--primary);
font-weight: 600;
transform: translateX(4px);
}
/* 焦点指示器 */
.focus-form:focus-within .focus-indicator {
background: var(--primary);
color: white;
}
示例 2: 嵌套元素的焦点传播
:focus-within 会向上传播到所有祖先元素,这使得多层嵌套的布局也能响应内部元素的焦点状态。
当内部任何输入框获得焦点时,我会变成橙色边框
当内部输入框获得焦点时,我会变成紫色边框
/* 外层容器 */
.outer-container:focus-within {
border-color: #f59e0b;
background: rgba(245, 158, 11, 0.05);
}
.outer-container:focus-within > .container-label {
color: #f59e0b;
}
/* 中层容器 */
.middle-container:focus-within {
border-color: #8b5cf6;
background: rgba(139, 92, 246, 0.05);
}
.middle-container:focus-within > .container-label {
color: #8b5cf6;
}
/* 内层容器 */
.inner-container:focus-within {
border-color: var(--primary);
background: var(--primary-light);
}
.inner-container:focus-within > .container-label {
color: var(--primary);
}
实际应用场景
以下是三个常见的实际应用场景,展示 :focus-within 如何提升用户体验。
场景 1: 搜索框容器焦点效果
/* 搜索框容器获得焦点时的样式 */
.search-container:focus-within {
border-color: var(--primary);
box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.1);
background: var(--primary-light);
}
/* 图标颜色变化 */
.search-container:focus-within .search-icon {
color: var(--primary);
}
/* 搜索按钮显示动画 */
.search-container:focus-within .search-btn {
opacity: 1;
transform: scale(1);
background: var(--primary);
color: white;
}
场景 2: 登录表单焦点高亮
/* 登录卡片获得焦点时提升 */
.login-card:focus-within {
border-color: var(--primary);
box-shadow: 0 8px 24px rgba(16, 185, 129, 0.15);
transform: translateY(-2px);
}
/* 标题颜色变化 */
.login-card:focus-within h3 {
color: var(--primary);
}
/* 当前字段标签高亮 */
.login-field:focus-within label {
color: var(--primary);
transform: translateX(4px);
}
/* 提交按钮激活 */
.login-card:focus-within .login-submit {
background: var(--primary);
color: white;
}
场景 3: 评论框焦点状态
/* 评论框获得焦点时的样式 */
.comment-box:focus-within {
border-color: var(--primary);
background: var(--primary-light);
}
/* 头像动画 */
.comment-box:focus-within .comment-avatar {
background: var(--primary);
transform: scale(1.1);
}
/* 操作按钮显示 */
.comment-box:focus-within .comment-actions {
opacity: 1;
}
/* 工具按钮渐入动画 */
.comment-box:focus-within .comment-tool {
transform: translateY(0);
opacity: 1;
}
/* 提交按钮激活 */
.comment-box:focus-within .comment-submit {
background: var(--primary);
color: white;
}
浏览器兼容性
:focus-within 在现代浏览器中有良好的支持,是一个可以放心使用的特性。
| 浏览器 | 版本支持 | 发布时间 |
|---|---|---|
| Chrome / Edge | ✓ 60+ | 2017年7月 |
| Firefox | ✓ 52+ | 2017年3月 |
| Safari | ✓ 10.1+ | 2017年3月 |
| iOS Safari | ✓ 10.3+ | 2017年3月 |
-
优先使用 - 相比
:has(:focus),:focus-within性能更好且支持更早 - 渐进增强 - 即使不支持,也不会影响基本功能,只是缺少视觉增强
- 无障碍友好 - 配合键盘导航使用,提升可访问性
- 避免过度使用 - 不要在每个元素上都使用,保持性能
- IE 浏览器不支持
:focus-within - 如需支持旧版浏览器,可以使用 JavaScript polyfill
- 避免在
:focus-within中使用复杂的动画,可能影响性能
总结
:focus-within 是一个强大且实用的伪类选择器,它让我们能够在不使用 JavaScript 的情况下,
根据内部元素的焦点状态来改变父容器的样式。
- 当元素自身或后代元素获得焦点时匹配
- 焦点状态向上传播到所有祖先元素
- 非常适合表单、搜索框、对话框等交互场景
- 相比
:has(:focus)性能更好,浏览器支持更早 - 配合过渡动画可以创造流畅的用户体验
在下一个演示中,我们将学习 :focus-visible,
它可以帮助我们区分鼠标点击和键盘导航的焦点状态,进一步优化用户体验。