:where() 伪类
零权重选择器,易于覆盖的默认样式
什么是 :where() 伪类?
:where() 伪类的功能与 :is() 类似,都可以简化选择器列表。
但它有一个独特的特性:零权重(specificity = 0)。
这意味着 :where() 本身不会增加选择器的优先级,使得样式更容易被覆盖。
这对于创建可覆盖的默认样式、重置样式库等场景非常有用。
- 零权重 - 不增加选择器优先级
- 易于覆盖 - 适合默认样式和基础样式库
- 简化代码 - 与 :is() 一样可以合并选择器
- 灵活控制 - 在需要低优先级时使用
基础语法
:where() 的语法与 :is() 完全相同,但优先级计算规则不同。
/* 基础语法 */
:where(selector1, selector2, selector3) {
/* 样式规则 */
}
/* 在复杂选择器中使用 */
:where(.header, .sidebar, .footer) a {
/* 匹配 .header a, .sidebar a, .footer a */
}
/* 与 :is() 的语法对比 */
:is(.header, .sidebar) a { } /* 权重: (0,1,1) */
:where(.header, .sidebar) a { } /* 权重: (0,0,1) - 零权重! */
:where() 的优先级始终为 0,无论其参数列表中包含什么选择器。 这与
:is() 取最高权重的规则完全不同。
/* :where() 的权重始终为 0 */
:where(#id, .class, div) { } /* 权重: (0,0,0) - 零权重! */
:where(.class, div) { } /* 权重: (0,0,0) - 零权重! */
/* 对比 :is() 的权重计算 */
:is(#id, .class, div) { } /* 权重: (1,0,0) - 取最高 */
:is(.class, div) { } /* 权重: (0,1,0) - 取最高 */
:is() - 优先级取参数中的最高值,适合需要保持优先级的场景
:where() - 优先级始终为 0,适合需要易于覆盖的默认样式
:is() vs :where() 权重对比
示例 1: 基础权重差异
/* 使用 :is() - 权重: (0,1,1) = 11 */
:is(.highlight) {
background: lightblue;
color: darkblue;
}
/* 使用 :where() - 权重: (0,0,0) = 0 */
:where(.highlight) {
background: lightgreen;
color: darkgreen;
}
/* 简单的类选择器 - 权重: (0,1,0) = 10 */
.override {
background: lightyellow;
color: darkorange;
}
/* 结果:
- :is(.highlight) 需要更高权重才能覆盖
- :where(.highlight) 很容易被 .override 覆盖 ✓ */
示例 2: 覆盖难易程度对比
使用 :is()
使用 :where()
/* 左侧:使用 :is() - 权重 (0,1,1) */
:is(.card, .panel) {
background: lightblue;
color: darkblue;
}
/* 简单类无法覆盖 ❌ */
.custom {
background: lightyellow; /* 不生效 */
}
/* 需要更高权重 */
.card.custom {
background: lightyellow; /* 生效 ✓ */
}
/* 右侧:使用 :where() - 权重 (0,0,0) */
:where(.card, .panel) {
background: lightgreen;
color: darkgreen;
}
/* 简单类就能覆盖 ✓ */
.custom {
background: lightyellow; /* 生效 ✓ */
}
示例 3: 权重计算详细对比
| 选择器 | 权重 | 说明 |
|---|---|---|
| :is(.a, .b) | (0,1,0) | 取最高权重 |
| :where(.a, .b) | (0,0,0) | 零权重 |
| :is(#id, .class) | (1,0,0) | 取 ID 的权重 |
| :where(#id, .class) | (0,0,0) | 仍然是零权重 |
| div :is(.a, .b) | (0,1,1) | div(1) + :is()最高权重(10) |
| div :where(.a, .b) | (0,0,1) | div(1) + :where()(0) |
/* :is() 取参数中的最高权重 */
:is(.a, .b) /* (0,1,0) */
:is(#id, .class) /* (1,0,0) - 取 ID */
div :is(.a, .b) /* (0,1,1) */
/* :where() 始终为零权重 */
:where(.a, .b) /* (0,0,0) */
:where(#id, .class) /* (0,0,0) - 仍然是 0! */
div :where(.a, .b) /* (0,0,1) - 只有 div */
/* 关键区别:
:is() 会影响整体权重
:where() 不会影响整体权重 */
零权重应用场景
场景 1: 可覆盖的默认样式
/* 使用 :where() 设置默认样式 - 权重 (0,0,0) */
:where(button, .btn) {
padding: 10px 20px;
border: 2px solid #ccc;
background: #f5f5f5;
color: #333;
cursor: pointer;
}
/* 简单的类就能覆盖 - 权重 (0,1,0) */
.primary {
background: green;
color: white;
border-color: green;
}
.danger {
background: red;
color: white;
border-color: red;
}
/* 优势:
- 默认样式不会干扰自定义样式
- 不需要使用 !important
- 不需要提高选择器权重 */
场景 2: 重置样式库
标题没有默认边距
段落没有默认边距
- 列表没有默认样式
- 没有项目符号
文章标题
这是文章的段落内容,有自定义的边距和颜色。
- 列表项 1
- 列表项 2
- 列表项 3
💡 重置样式使用 :where(),项目样式不需要高权重就能覆盖
/* reset.css - 使用 :where() 创建重置样式 */
:where(h1, h2, h3, h4, h5, h6) {
margin: 0;
padding: 0;
font-weight: 600;
}
:where(p, ul, ol) {
margin: 0;
padding: 0;
}
:where(ul, ol) {
list-style: none;
}
/* 项目样式 - 简单选择器就能覆盖 */
.article h2 {
margin: 20px 0 10px; /* 轻松覆盖 ✓ */
color: blue;
}
.article p {
margin: 15px 0; /* 轻松覆盖 ✓ */
}
.article ul {
list-style: disc; /* 轻松覆盖 ✓ */
padding-left: 20px;
}
/* 如果不用 :where(),需要这样覆盖:
.article h2 { } 无法覆盖 h1, h2, h3, h4, h5, h6 { }
需要更高权重或 !important */
场景 3: 组件库默认样式
💡 组件库提供默认样式,用户可以轻松自定义而不需要高权重选择器
/* component-library.css - 使用 :where() */
:where(input, textarea, select) {
width: 100%;
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1rem;
}
:where(input, textarea, select):focus {
border-color: blue;
}
/* 用户的项目样式 - 简单类名即可覆盖 */
.custom-input {
border: 2px solid green; /* 轻松覆盖 ✓ */
border-radius: 8px;
padding: 12px 16px;
}
.error-input {
border: 2px solid red; /* 轻松覆盖 ✓ */
background: #fee;
}
/* 优势:
- 组件库不会强制样式
- 用户不需要 !important
- 保持样式的可维护性 */
- 重置样式:创建易于覆盖的 CSS 重置
- 组件库:提供默认样式但不强制使用
- 工具类:创建低优先级的实用工具类
- 主题样式:设置可被轻松自定义的主题
- 避免冲突:减少样式优先级冲突
使用 :where() 当:
- 创建默认样式或重置样式
- 希望样式容易被覆盖
- 构建组件库或框架
- 避免优先级冲突
使用 :is() 当:
- 简化选择器列表
- 需要保持正常的优先级
- 不关心覆盖难易程度
- 需要与其他选择器竞争优先级
浏览器兼容性
:where() 伪类在现代浏览器中得到了广泛支持:
| 浏览器 | 支持版本 | 状态 |
|---|---|---|
| Chrome / Edge | 88+ | ✓ |
| Firefox | 78+ | ✓ |
| Safari | 14+ | ✓ |
| Opera | 74+ | ✓ |
:where() 与 :is() 在同一时期获得浏览器支持。
如果需要支持旧版浏览器,可以使用传统的选择器列表作为降级方案。