
本文详解如何利用 css `:has()` 选择器,在存在中间包裹容器(如 `
当 HTML 结构中 <kendo-textbox> 被嵌套在 <div> 中,而 <kendo-label> 与其同级但不直接相邻时(即结构为 kendo-label → div → kendo-textbox),无法再使用 +(相邻兄弟)组合器。此时必须改用 :has() 的后代关系表达能力:将整个路径写入单个 :has() 函数内,使其语义变为“选择后面紧邻的 div,且该 div 内部包含处于 :focus-within 状态的 .k-input-solid 元素”。
✅ 正确写法如下:
kendo-label:has(+ div .k-input-solid:focus-within) .k-label {
color: var(--blue-05);
font-weight: 600;
}⚠️ 关键说明:
- + div 表示「下一个相邻兄弟元素是 <div>」;
- div .k-input-solid:focus-within 是其内部的后代选择器,表示该 <div> 内任意层级下存在获得焦点或其子元素获得焦点的 .k-input-solid(推荐用 :focus-within,兼容输入框内含 <input> 等子控件的场景);
- 整个 :has(+ div .k-input-solid:focus-within) 必须写在一个 :has() 中——不可拆分为多个 :has() 链式调用(如 :has(+ div):has(+ .k-input-solid)),因为后者仍要求两个条件分别作用于同一级后续兄弟,逻辑上不成立。
? 实际 HTML 示例验证:
立即学习“前端免费学习笔记(深入)”;
<kendo-label> <label class="k-label">用户名</label> </kendo-label> <div> <kendo-textbox class="k-input-solid"></kendo-textbox> </div>
只要用户点击或 Tab 进入该 <kendo-textbox>(或其内部原生 <input>),.k-label 即实时高亮为蓝色加粗。
? 补充建议:
- 若组件库实际渲染出的是 <input> 而非自定义元素,可微调为 :has(+ div input.k-input-solid:focus) 提升兼容性;
- 目前 :has() 已获 Chrome 105+、Firefox 121+、Safari 15.4+ 原生支持,生产环境使用前建议通过 caniuse.com/:has 检查目标浏览器覆盖率;
- 不要尝试用 :focus 替代 :focus-within —— 后者能正确响应 <kendo-textbox> 内部 <input> 聚焦,而前者仅匹配元素自身聚焦(对 Web Component 封装的组件通常无效)。
此方案无需 JavaScript、不侵入组件内部结构,纯 CSS 实现语义清晰、性能高效,是现代前端样式化跨容器交互的理想实践。










