CSS其他伪类与伪元素:否定、匹配等高级选择器详解
1 否定伪类 :not() 详解
1.1 基本语法与参数
否定伪类 :not() 是CSS3中引入的一个重要功能,它允许开发者选择不匹配特定选择器的元素。这种选择器被称为反选伪类(negation pseudo-class),可以显著优化CSS代码的编写方式,减少对重置样式的需求。
:not() 伪函数接受一个或多个选择器作为参数,然后匹配那些不匹配这些参数的元素。其基本语法如下:
:not(selector) {
/* 样式声明 */
}需要注意的是,传递给 :not() 的参数可以是标签选择器、类选择器、ID选择器、属性选择器或其他伪类选择器,但不能是伪元素选择器或另一个否定伪类选择器。例如,以下用法是无效的:
/* 无效的 :not() 用法 */
:not(::before) { /* 伪元素不允许 */ }
:not(:not(.same)) { /* 不允许嵌套 :not() */ }1.2 实际应用示例
以下是一个完整的HTML页面示例,展示了 :not() 伪类的实际应用:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>:not() 伪类示例</title>
<style>
/* 选择所有不是<p>的元素 */
body :not(p) {
margin-left: 20px;
}
/* 选择既不包含.special类也不是<div>的元素 */
body :not(.special):not(div) {
font-style: italic;
}
/* 选择所有没有disabled属性的输入元素 */
input:not([disabled]) {
background-color: #f0f8ff;
border: 2px solid #4CAF50;
}
/* 选择非第一个子元素的列表项 */
li:not(:first-child) {
border-top: 1px solid #ddd;
padding-top: 10px;
}
</style>
</head>
<body>
<h1>页面标题</h1>
<p>这是一个普通段落。</p>
<p class="special">这是一个特殊段落。</p>
<div>这是一个div元素。</div>
<ul>
<li>第一个列表项</li>
<li>第二个列表项</li>
<li>第三个列表项</li>
</ul>
<input type="text" placeholder="可输入文本框">
<input type="text" disabled placeholder="禁用文本框">
</body>
</html>在这个示例中,我们使用了多种 :not() 表达式:
body :not(p)选择body中所有不是段落元素的元素body :not(.special):not(div)选择既不包含special类也不是div的元素input:not([disabled])选择所有未禁用的输入框li:not(:first-child)选择除第一个列表项外的所有列表项
通过合理使用 :not() 伪类,我们可以编写出更加简洁、易于维护的CSS代码,避免了频繁使用重置样式覆盖原有样式的情况。
2 任意匹配伪类 :is() 和 :where()
2.1 功能与语法对比
:is() 和 :where() 是两个功能相似但有着关键差异的CSS伪类,它们都用于将一组选择器作为一个整体进行匹配,从而简化复杂选择器的编写。这两个伪类都可以接受一个选择器列表作为参数,并匹配该列表中任意一个选择器可以选择的元素。
它们的基本语法如下:
/* :is() 语法 */
:is(selector1, selector2, selector3) {
/* 样式声明 */
}
/* :where() 语法 */
:where(selector1, selector2, selector3) {
/* 样式声明 */
}虽然功能相似,但两者在优先级上有显著区别。:is() 伪类会采用其参数中优先级最高的选择器的优先级,而 :where() 伪类的优先级始终为0。这一差异使得 :where() 在需要低优先级覆盖样式时特别有用。
2.2 优先级差异与容错机制
为了更好地理解 :is() 和 :where() 的优先级差异,请参考以下对比表格:
| 特性 | :is() | :where() |
|---|---|---|
| 优先级 | 采用参数中最高优先级 | 始终为0 |
| 容错性 | 是 | 是 |
| 浏览器支持 | 现代浏览器广泛支持 | 现代浏览器广泛支持 |
| 适用场景 | 需要正常优先级的情况 | 需要低优先级便于覆盖的情况 |
以下是一个完整的示例,展示了两者的区别:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>:is() 和 :where() 示例</title>
<style>
/* 使用 :is() - 优先级相当于 header p */
:is(header, section, footer) p {
color: blue;
font-size: 16px;
}
/* 使用 :where() - 优先级为0,相当于 p */
:where(header, section, footer) .special {
color: red;
font-style: italic;
}
/* 对比组:这个规则会覆盖上面的 :where() 规则 */
.special {
color: green !important;
font-weight: bold;
}
/* 容错机制示例 - 即使 :unsupported 是无效选择器,整体仍有效 */
:is(.valid, :unsupported) {
background-color: #f0f0f0;
padding: 10px;
}
/* 传统写法等效对比 */
header p, section p, footer p {
border-left: 3px solid blue;
padding-left: 10px;
}
</style>
</head>
<body>
<header>
<p>头部段落(蓝色)</p>
<p class="special">头部特殊段落(绿色粗体,:where()被覆盖)</p>
</header>
<section>
<p>内容区段落(蓝色)</p>
<div class="valid">有效元素(灰色背景)</div>
</section>
<footer>
<p>底部段落(蓝色)</p>
</footer>
</body>
</html>在这个示例中,我们可以观察到以下几个关键点:
:is()的优先级行为::is(header, section, footer) p的优先级与header p相同,因此会正常应用蓝色文本样式。:where()的低优先级:尽管:where(header, section, footer) .special包含了类选择器,但由于:where()的优先级为0,该规则被简单的.special选择器覆盖。- 容错机制:在
:is(.valid, :unsupported)中,即使:unsupported是一个无效的选择器,整个规则也不会失效,仍然会应用到有效的.valid元素上。 - 代码简化效果:使用
:is()可以将多个逗号分隔的选择器组合成一个简洁的表达,提高代码可读性。
值得注意的是,:is() 和 :where() 都支持可容错选择器解析,这意味着当其中一个选择器无效时,不会使整个规则失效,其他有效的选择器仍然会被应用。这一特性使它们在处理浏览器兼容性或未知选择器时更加稳健。
3 关联伪类 :has() 的强大应用
3.1 语法与浏览器支持
:has() 伪类是CSS选择器Level 4规范中引入的一个革命性功能,它允许开发者根据元素的后代元素来选择该元素,实现了类似”父选择器”和”前面兄弟选择器”的效果。这一功能对CSS的开发有着颠覆性的影响,因为它首次使开发者能够根据子元素的状态来选择父元素。
:has() 伪类的基本语法如下:
parent:has(child) {
/* 样式声明 */
}
element:has(+ sibling) {
/* 样式声明 */
}尽管 :has() 伪类规范制定得很早,但浏览器的支持却相对较慢。不过,目前大多数现代浏览器的最新版本已经支持了这一功能。在实际使用前,建议检查目标浏览器的支持情况。
3.2 实际应用场景
以下是展示 :has() 伪类多种应用场景的完整示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>:has() 伪类示例</title>
<style>
/* 选择包含<svg>元素的<a>元素 */
a:has(> svg) {
background-color: #f8f9fa;
padding: 8px 12px;
border-radius: 4px;
display: inline-flex;
align-items: center;
}
/* 选择后面跟随<p>元素的<h1>元素 */
h1:has(+ p) {
border-bottom: 2px solid #4CAF50;
padding-bottom: 10px;
margin-bottom: 5px;
}
/* 选择包含.selected类的列表项的无序列表 */
ul:has(li.selected) {
border: 2px solid #ff9800;
background-color: #fff3e0;
}
/* 选择包含空白的输入字段的表单组 */
.form-group:has(input:placeholder-shown) {
opacity: 0.7;
}
/* 选择包含至少一个图片的article元素 */
article:has(img) {
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
/* 选择包含聚焦输入框的表单 */
form:has(input:focus) {
background-color: #f0f8ff;
}
/* 卡片布局增强 */
.card:has(.featured) {
transform: scale(1.05);
z-index: 1;
}
</style>
</head>
<body>
<h1>带段落的标题</h1>
<p>这个标题有下边框,因为它后面跟着段落。</p>
<h1>独立标题</h1>
<a href="#">
普通链接
</a>
<a href="#">
带图标的链接
<svg width="16" height="16" viewBox="0 0 16 16" style="margin-left:5px;">
<circle cx="8" cy="8" r="7" fill="none" stroke="currentColor" stroke-width="2"/>
</svg>
</a>
<ul>
<li>普通列表项</li>
<li class="selected">选中的列表项</li>
<li>另一个普通列表项</li>
</ul>
<div class="form-group">
<input type="text" placeholder="请输入内容">
</div>
<div class="form-group">
<input type="text" value="已填写内容">
</div>
<article>
<h2>带图片的文章</h2>
<img src="https://via.placeholder.com/150" alt="示例图片">
<p>这篇文章有阴影效果,因为它包含图片。</p>
</article>
<article>
<h2>无图片的文章</h2>
<p>这篇文章没有阴影效果。</p>
</article>
<form>
<div class="form-group">
<label>姓名:</label>
<input type="text" placeholder="点击我会使表单变背景色">
</div>
</form>
<div class="card">
<h3>普通卡片</h3>
<p>这是一个普通卡片。</p>
</div>
<div class="card">
<h3>特色卡片</h3>
<p class="featured">这是一个特色卡片,它会放大。</p>
</div>
</body>
</html>在这个示例中,我们展示了 :has() 伪类的多种强大应用:
- 父选择器效果:通过
a:has(> svg)选择包含SVG图标的所有链接元素,并为其添加特殊样式。 - 前面兄弟选择器效果:使用
h1:has(+ p)选择后面紧跟着段落的所有一级标题。 - 条件性容器样式:通过
ul:has(li.selected)和article:has(img)选择包含特定子元素的容器。 - 表单状态管理:利用
:has(input:placeholder-shown)和:has(input:focus)根据表单字段的状态为整个表单或表单组添加样式。 - 交互式组件增强:使用
.card:has(.featured)为包含特定元素的卡片添加突出显示效果。
需要注意的是,虽然 :has() 伪类功能强大,但由于其性能特性(浏览器需要检查多个元素的关系),在大型文档中应谨慎使用,避免复杂的 :has() 表达式影响页面渲染性能。
4 伪元素的扩展应用
4.1 常见伪元素详解
伪元素是CSS提供的强大功能,它们允许开发者选择和样式化元素的特定部分,而无需添加额外的HTML元素。与伪类选择元素的状态不同,伪元素选择的是元素的某个特定部分。
最常见的伪元素包括:
::before和::after:在元素内容的前面或后面插入生成的内容::first-letter:选择块级元素的第一行的第一个字母::first-line:选择块级元素的第一行::selection:选择用户选中或高亮的部分::marker:选择列表项的标记框(如无序列表的点或有序列表的数字)
4.2 内容生成与文本装饰
以下是一个展示多种伪元素应用的完整示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>伪元素应用示例</title>
<style>
/* ::before 和 ::after 示例 */
blockquote::before {
content: "“";
font-size: 3em;
color: #4CAF50;
line-height: 0.1em;
vertical-align: -0.4em;
}
blockquote::after {
content: "”";
font-size: 3em;
color: #4CAF50;
line-height: 0.1em;
vertical-align: -0.4em;
}
.feature::before {
content: "✓";
color: #4CAF50;
font-weight: bold;
margin-right: 8px;
}
/* ::first-letter 示例 */
p::first-letter {
font-size: 2em;
color: #d32f2f;
font-weight: bold;
float: left;
line-height: 1;
margin-right: 5px;
}
/* ::first-line 示例 */
p::first-line {
font-weight: bold;
color: #1976d2;
text-transform: uppercase;
}
/* ::selection 示例 */
::selection {
background-color: #ffeb3b;
color: #000;
}
/* ::marker 示例 */
li::marker {
color: #d32f2f;
font-weight: bold;
}
/* 自定义列表样式 */
.custom-list li::marker {
content: "➤ ";
color: #4CAF50;
}
/* 工具提示效果 */
.tooltip {
position: relative;
border-bottom: 1px dotted #000;
cursor: help;
}
.tooltip::after {
content: attr(data-tooltip);
position: absolute;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: #fff;
padding: 5px 10px;
border-radius: 4px;
white-space: nowrap;
opacity: 0;
transition: opacity 0.3s;
pointer-events: none;
font-size: 14px;
font-weight: normal;
text-transform: none;
}
.tooltip:hover::after {
opacity: 1;
}
</style>
</head>
<body>
<h1>伪元素演示</h1>
<blockquote>
这是一个使用::before和::after添加引号的块引用。注意开头和结尾的大型引号。
</blockquote>
<div class="feature">特色功能一</div>
<div class="feature">特色功能二</div>
<div class="feature">特色功能三</div>
<p>这个段落演示了::first-letter和::first-line伪元素的效果。注意首字母的下沉和变色,以及第一行的大写和蓝色。段落的其余部分保持正常样式。伪元素使我们能够创建视觉上吸引人的排版效果,而无需修改HTML结构。</p>
<p>尝试选中一些文本,可以看到::selection伪元素的效果,它改变了文本选中时的背景和文字颜色。</p>
<ul>
<li>默认列表项</li>
<li>另一个列表项</li>
<li>注意列表标记的颜色</li>
</ul>
<ul class="custom-list">
<li>自定义标记列表</li>
<li>使用自定义箭头作为标记</li>
</ul>
<div class="tooltip" data-tooltip="这是一个提示信息">
鼠标悬停在这里查看工具提示
</div>
</body>
</html>在这个示例中,我们展示了多种伪元素的应用场景:
- 内容生成:使用
::before和::after为blockquote元素添加装饰性引号,为特色功能列表添加勾选标记。 - 文本装饰:通过
::first-letter创建首字母下沉效果,使用::first-line为段落第一行添加特殊样式。 - 交互反馈:利用
::selection改变文本选中样式,增强用户体验。 - 列表定制:通过
::marker自定义列表标记的样式,创建独特的列表外观。 - 工具提示:结合
::after和content: attr()函数,实现纯CSS工具提示效果。
需要注意的是,使用 ::before 和 ::after 伪元素时必须指定 content 属性,即使将其设置为空字符串(content: "")。此外,虽然伪元素在选择器中的优先级与普通伪类相同,但它们可以实现仅通过修改HTML结构难以达到的效果。
5 高级选择器综合应用与性能优化
5.1 综合应用实例
在实际项目中,高级选择器往往不是单独使用的,而是结合多种选择器创建精确且强大的样式规则。以下是一个综合应用多种高级选择器的完整示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>高级选择器综合应用</title>
<style>
/* 1. 使用 :is() 简化选择器组 */
:is(header, main, footer) :is(h1, h2, h3) {
font-family: 'Arial', sans-serif;
margin-bottom: 0.5em;
}
/* 2. 使用 :where() 添加低优先级样式 */
:where(article, section) p {
line-height: 1.6;
margin-bottom: 1em;
}
/* 3. 使用 :not() 排除特定元素 */
article :not(.exclude) {
opacity: 0.95;
}
/* 4. 使用 :has() 创建条件布局 */
.grid:has(.featured) {
grid-template-columns: 2fr 1fr 1fr;
gap: 15px;
}
/* 5. 结合伪元素增强设计 */
article:has(h2) > p:first-of-type::first-line {
font-variant: small-caps;
letter-spacing: 0.5px;
}
/* 6. 表单状态的高级选择 */
form:has(input:invalid) {
border-left: 3px solid #f44336;
}
form:has(input:valid) {
border-left: 3px solid #4CAF50;
}
/* 7. 使用属性选择器增强交互 */
a[href^="https"]:not([target="_blank"])::after {
content: " 🔒";
font-size: 0.8em;
}
/* 8. 卡片系统的高级选择器 */
.card:not(:has(img)) {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.card:has(.urgent) {
border: 2px solid #ff5252;
animation: pulse 2s infinite;
}
/* 动画定义 */
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(255, 82, 82, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(255, 82, 82, 0); }
100% { box-shadow: 0 0 0 0 rgba(255, 82, 82, 0); }
}
/* 布局样式 */
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
margin: 20px 0;
}
.card {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
form {
padding: 20px;
background: #f9f9f9;
margin: 20px 0;
transition: all 0.3s ease;
}
input {
display: block;
width: 100%;
padding: 8px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 4px;
}
/* 内容样式 */
.exclude {
background-color: #fff3e0;
padding: 10px;
border-radius: 4px;
}
.urgent {
color: #f44336;
font-weight: bold;
}
</style>
</head>
<body>
<header>
<h1>网站标题</h1>
<h2>子标题</h2>
</header>
<main>
<article>
<h2>带特色内容的主要文章</h2>
<p>这篇文章的第一行会使用小型大写字母显示,这是通过组合:has()和::first-line伪元素实现的。其余内容保持正常样式。</p>
<p>普通段落,没有特殊样式。</p>
<div class="exclude">这个元素被排除在不透明度调整之外。</div>
</article>
<section>
<h3>卡片网格系统</h3>
<div class="grid">
<div class="card">
<h4>普通卡片</h4>
<p>没有图片的卡片,具有渐变背景。</p>
</div>
<div class="card">
<h4>带图片的卡片</h4>
<img src="https://via.placeholder.com/150" alt="示例">
<p>这个卡片包含图片,没有渐变背景。</p>
</div>
<div class="card">
<h4>紧急卡片</h4>
<p class="urgent">这个卡片有紧急内容,带有脉冲动画边框。</p>
</div>
</div>
</section>
<section>
<h3>表单验证状态</h3>
<form>
<label>必填字段:</label>
<input type="text" required placeholder="请输入内容">
<label>电子邮件:</label>
<input type="email" required placeholder="输入有效邮箱">
</form>
</section>
<section>
<h3>链接安全指示器</h3>
<p>
<a href="https://example.com">安全链接</a> |
<a href="http://insecure.example.com">不安全链接</a>
</p>
</section>
</main>
<footer>
<h3>页脚信息</h3>
<p>版权所有 © 2023</p>
</footer>
</body>
</html>5.2 优先级计算与性能优化
优先级计算规则
当使用高级选择器时,理解CSS优先级计算规则至关重要。以下是优先级计算的关键点:
:is()和:has()的优先级:采用参数中选择器的最高优先级:where()的优先级:始终为0,不影响优先级计算:not()的优先级:由括号内的选择器决定
以下表格展示了不同选择器的优先级权重:
| 选择器示例 | 优先级计算 | 说明 |
|---|---|---|
#header .link | 100 + 10 = 110 | ID + 类 |
:is(#header, .nav) .link | 100 + 10 = 110 | 取最高优先级参数 |
:where(#header, .nav) .link | 0 + 10 = 10 | :where()优先级为0 |
a:not(.external) | 1 + 10 = 11 | 标签 + 类 |
性能优化建议
虽然高级选择器功能强大,但不当使用可能影响页面性能。以下是一些优化建议:
- 避免过度复杂的选择器:特别是包含大量回溯或复杂参数的选择器
- 优先使用类选择器:对于频繁使用的样式,类选择器通常性能更好
- 合理使用
:has():由于:has()需要浏览器进行更多计算,应谨慎使用 - 利用浏览器的优化:现代浏览器已对常用选择器进行了优化,但仍需注意选择器复杂度
/* 不推荐 - 过于复杂的选择器 */
body > div:first-of-type:has(nav > ul > li:first-child > a[href^="#"]) ~ main article:not(.draft) p:first-of-type::first-letter {
font-size: 3em;
}
/* 推荐 - 简化选择器,使用类替代 */
.article-lead::first-letter {
font-size: 3em;
}通过合理组合使用高级选择器,并遵循性能优化最佳实践,开发者可以创建既强大又高效的CSS规则,提升用户体验和代码维护性。
总结
CSS高级伪类与伪元素大大扩展了CSS选择器的能力,使开发者能够更精确地选择和样式化文档中的元素。以下是本教程的主要知识点总结:
| 知识点 | 详细内容 |
|---|---|
否定伪类 :not() | 选择不匹配指定选择器的元素,可接受简单选择器作为参数,但不能嵌套使用 |
任意匹配伪类 :is() | 将选择器列表作为参数,选择匹配列表中任一选择器的元素,优先级采用参数中最高优先级 |
任意匹配伪类 :where() | 功能与:is()相同,但优先级始终为0,适合创建易于覆盖的样式 |
关联伪类 :has() | 根据元素的后代元素来选择该元素,实现父选择器和前面兄弟选择器效果 |
伪元素 ::before/::after | 在元素内容前/后插入生成内容,必须指定content属性 |
| 伪元素 `::first-letter | 选择块级元素第一行的第一个字母,常用于首字母下沉效果 |
| 伪元素 `::first-line | 选择块级元素的第一行,可应用有限的样式属性 |
| 伪元素 `::selection | 选择用户选中或高亮的部分,可定义背景色和文字颜色 |
| 伪元素 `::marker | 选择列表项的标记框,可自定义列表标记样式 |
| 优先级计算 | :is()和:has()采用参数中最高优先级,:where()优先级为0,:not()优先级由括号内选择器决定 |
| 性能优化 | 避免过度复杂的选择器,优先使用类选择器,谨慎使用:has() |
通过掌握这些高级选择器,开发者可以编写出更简洁、更灵活且更易维护的CSS代码,创建出视觉丰富、交互性强的现代网页设计。

