CSS 高级伪类指南::has、:is、:where 等 8 个实用选择器解析
除了常用的 :hover、:active、:focus,css 中还有一些冷门但非常实用的伪类,可以帮助你更优雅地处理各种交互场景。本文整理了 8 个值得掌握的 CSS 伪类,附带代码示例和兼容性说明。
1. :has() — 父级选择器
:has() 是 CSS 中一项重要的特性,允许根据子元素的存在与否来选择父元素,一定程度上可以减少对 JavaScript 的依赖。
/* 选择包含错误提示子元素的卡片 */
.card:has(.error) {
border: 2px solid red;
}
/* 选择包含图片的链接 */
a:has(img) {
text-decoration: none;
}
/* 选择表单中有无效输入的容器 */
.form-group:has(:invalid) {
background: #ffeeee;
}实际应用:
/* 当卡片内没有图片时,调整布局 */
.card:not(:has(img)) {
grid-template-columns: 1fr;
}
/* 当标题超长时,隐藏描述 */
.card:has(h1.long-title) .description {
display: none;
}兼容性:Chrome 105+ | Safari 15.4+ | Firefox 121+
2. :is() 和 :where() — 选择器分组
这两个伪类用于简化复杂选择器的写法,提升代码可读性。
/* 传统写法 */
.card h1,
.card h2,
.card h3 {
color: #333;
margin-top: 0;
}
/* :is() 一行搞定 */
.card :is(h1, h2, h3) {
color: #333;
margin-top: 0;
}:is() 与 :where() 的区别
/* :is() 优先级正常 */
.card :is(h1, h2) {
color: red; /* 优先级 (0,1,1) */
}
/* :where() 优先级为 0,可被覆盖 */
.card :where(h1, h2) {
color: blue; /* 优先级 (0,0,0) */
}
/* 后面的样式可以覆盖 :where() */
.card h1 {
color: green; /* 覆盖成功 */
}
/* 但不能覆盖 :is() */
.card h1 {
color: green; /* 无法覆盖 */
}应用场景:
:is():需要保持选择器优先级时使用
:where():用于重置样式或降低优先级时使用
兼容性:Chrome 88+ | Firefox 78+ | Safari 14+
3. :not() — 否定选择器
:not() 用于排除特定元素,支持多参数。
/* 选择所有段落,排除 .intro 和 .footer */
p:not(.intro, .footer) {
margin-bottom: 1rem;
}
/* 选择所有 input,排除 checkbox 和 radio */
input:not([type="checkbox"]):not([type="radio"]) {
width: 100%;
}
/* 选择所有链接,排除 .external 和 #homepage */
a:not(.external, #homepage) {
color: blue;
}实际案例:
/* 隐藏所有元素,除了活动项 */
.list-item:not(.active) {
display: none;
}
/* 所有按钮加样式,排除禁用的 */
button:not(:disabled) {
cursor: pointer;
opacity: 1;
}
/* 非空元素添加边框 */
*:not(:empty) {
border: 1px solid #eee;
}兼容性:广泛支持(多参数需 Chrome 88+ | Firefox 84+ | Safari 9+)
4. :target — URL 锚点定位
:target 根据 URL 中的 # 锚点改变样式,可实现无 JavaScript 的页面内跳转高亮。
/* 当用户访问 #section1 时 */
#section1:target {
background: yellow;
padding: 20px;
}
/* 当访问任何锚点时 */
:target {
animation: highlight 2s ease;
}
@keyframes highlight {
0% { background: yellow; }
100% { background: transparent; }
}实际应用:
<div id="intro">内容...</div>
<div id="details">内容...</div>/* 当用户访问 #details 时,显示详情面板 */
#details:target .panel {
display: block;
animation: slideIn 0.3s ease;
}
/* 高亮当前章节 */
[id]:target {
border-left: 4px solid #4fd1c5;
padding-left: 16px;
}适用场景:
无 JavaScript 的 Tab 切换
FAQ 展开/折叠
文档章节高亮
兼容性:所有现代浏览器
5. :focus-within — 子元素获得焦点
当元素自身或子元素获得焦点时触发,适合实现容器级的焦点反馈。
/* 输入框获得焦点时,容器也触发样式 */
.form-control:focus-within {
border-color: #4fd1c5;
background: #f0f9ff;
}
/* 当表单内有任何输入框获得焦点时 */
form:focus-within button[type="submit"] {
background: #4fd1c5;
transform: scale(1.05);
}实际案例:
/* 搜索框聚焦时,显示下拉建议 */
.search-container:focus-within .suggestions {
display: block;
}
/* 模态框内的输入框聚焦时,模态框高亮 */
.modal:focus-within {
box-shadow: 0 0 0 4px rgba(79, 209, 197, 0.2);
}
/* 导航菜单聚焦时,显示子菜单 */
.nav-item:focus-within .submenu {
opacity: 1;
transform: translateY(0);
}兼容性:Chrome 60+ | Firefox 52+ | Safari 10.1+
6. :checked — 复选框状态
:checked 用于选中状态的复选框或单选框,可实现无 JavaScript 的交互效果。
/* 复选框选中时,改变样式 */
input[type="checkbox"]:checked + label {
text-decoration: line-through;
color: #999;
}
/* 实现开关 */
.toggle-switch input[type="checkbox"]:checked + .slider {
background: #4fd1c5;
}
.toggle-switch input[type="checkbox"]:checked + .slider:before {
transform: translateX(26px);
}高级应用:手风琴菜单
.accordion input[type="radio"]:checked ~ .content {
max-height: 500px;
padding: 20px;
}
.accordion input[type="radio"]:checked ~ .header .icon {
transform: rotate(180deg);
}<div class="accordion">
<input type="radio" name="accordion" id="item1" checked>
<label class="header" for="item1">
标题 1 <span class="icon">▼</span>
</label>
<div class="content">内容...</div>
</div>兼容性:所有现代浏览器
7. :placeholder-shown — 占位符显示状态
:placeholder-shown 用于匹配占位符可见的输入框,常用于实现浮动标签效果。
/* 当占位符显示时(空输入框) */
input:placeholder-shown + label {
position: absolute;
top: 12px;
font-size: 16px;
}
/* 当占位符消失时(有内容) */
input:not(:placeholder-shown) + label {
position: absolute;
top: -8px;
font-size: 12px;
background: white;
padding: 0 4px;
color: #4fd1c5;
}实际案例:浮动标签
.input-group input:placeholder-shown ~ .label {
transform: translateY(0);
}
.input-group input:not(:placeholder-shown) ~ .label,
.input-group input:focus ~ .label {
transform: translateY(-24px);
font-size: 12px;
color: #4fd1c5;
}兼容性:Chrome 47+ | Firefox 52+ | Safari 9+
8. :blank — 空内容选择
:blank 用于选择没有内容的元素(包括空白节点),适用于隐藏空元素或显示占位内容。
/* 选择空段落 */
p:blank {
display: none;
}
/* 空单元格加虚线边框 */
td:blank {
border: 1px dashed #ccc;
}实际应用:
/* 空列表项隐藏 */
li:blank {
display: none;
}
/* 空提示框显示占位文字 */
.message:blank::before {
content: "暂无消息";
color: #999;
}兼容性:实验性特性,目前 Chrome 和 Firefox 部分版本需启用实验性 Web 平台特性才支持
结语
以上 8 个 CSS 伪类在不同场景下各有用途,合理使用可以简化代码结构、减少 JavaScript 依赖。可以根据项目需求逐步尝试引入。
本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!