:is() 伪类

简化选择器列表,提高代码可读性

什么是 :is() 伪类?

:is() 伪类允许你将多个选择器组合成一个列表,避免重复编写相同的选择器部分。 它可以大幅简化 CSS 代码,提高可读性和可维护性。

:is() 出现之前,如果要为多个不同区域的相同元素设置样式,需要重复编写完整的选择器。 现在,你可以使用 :is() 将这些选择器合并为一个简洁的规则。

  • 简化代码 - 减少重复的选择器模式
  • 提高可读性 - 更清晰地表达选择器的意图
  • 易于维护 - 修改时只需更新一处
  • 灵活组合 - 可以在选择器的任何位置使用

基础语法

:is() 接受一个选择器列表作为参数,匹配列表中任意一个选择器。

/* 基础语法 */
:is(selector1, selector2, selector3) {
  /* 样式规则 */
}

/* 等价于传统写法 */
selector1,
selector2,
selector3 {
  /* 样式规则 */
}

/* 在复杂选择器中使用 */
:is(.header, .sidebar, .footer) a {
  /* 匹配 .header a, .sidebar a, .footer a */
}

/* 可以在任何位置使用 */
article :is(h1, h2, h3) {
  /* 匹配 article 内的所有 h1, h2, h3 */
}

/* 多个 :is() 组合使用 */
:is(.dark, .light) :is(button, a) {
  /* 匹配 .dark button, .dark a, .light button, .light a */
}
💡 优先级计算规则

:is() 的优先级由其参数列表中优先级最高的选择器决定。 即使实际匹配的是低优先级选择器,整个 :is() 的权重也会取最高值。

/* :is() 的权重取决于参数中的最高权重 */
:is(#id, .class, div) { }  /* 权重: (1,0,0) - 取 #id 的权重 */
:is(.class, div) { }       /* 权重: (0,1,0) - 取 .class 的权重 */
⚠️ 容错性

:is() 具有容错性。如果列表中某个选择器无效,浏览器会忽略它,继续处理其他有效选择器。 这与传统的选择器列表不同,传统列表中一个无效选择器会导致整个规则失效。

传统写法 vs :is() 对比

示例 1: 多区域链接样式

效果预览

💡 悬停在链接上查看效果

❌ 传统写法 - 重复代码
/* 需要重复写三次完整的选择器 */
.header a:hover,
.sidebar a:hover,
.footer a:hover {
  background: purple;
  color: white;
}
✅ 使用 :is() - 简洁清晰
/* 只需写一次,代码更简洁 */
:is(.header, .sidebar, .footer) a:hover {
  background: purple;
  color: white;
}

/* 代码量减少 60%+ */

示例 2: 嵌套选择器简化

效果预览

一级标题

这是一段文本内容。

二级标题

这是另一段文本内容。

三级标题

所有标题都有统一的样式。

❌ 传统写法 - 冗长重复
/* 需要列出所有标题标签 */
article h1,
article h2,
article h3,
article h4,
article h5,
article h6 {
  color: blue;
  border-left: 4px solid blue;
}

/* 修改时需要改两处 */
article h1:first-child,
article h2:first-child,
article h3:first-child,
article h4:first-child,
article h5:first-child,
article h6:first-child {
  margin-top: 0;
}
✅ 使用 :is() - 一目了然
/* 清晰表达"所有标题"的意图 */
article :is(h1, h2, h3, h4, h5, h6) {
  color: blue;
  border-left: 4px solid blue;
}

/* 易于组合其他伪类 */
article :is(h1, h2, h3, h4, h5, h6):first-child {
  margin-top: 0;
}

示例 3: 复杂选择器组合

效果预览
Card: 链接按钮
Panel: 链接按钮
Widget: 链接按钮

💡 所有容器内的按钮和链接都有统一样式

❌ 传统写法 - 6 个选择器
/* 需要写 3×2=6 个选择器组合 */
.card button,
.card a.btn,
.panel button,
.panel a.btn,
.widget button,
.widget a.btn {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 8px 16px;
  /* ... 更多样式 */
}
✅ 使用 :is() - 1 个选择器
/* 两个 :is() 组合,清晰表达意图 */
:is(.card, .panel, .widget) :is(button, a.btn) {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 8px 16px;
  /* ... 更多样式 */
}

/* 代码量减少 83%! */

实际应用场景

场景 1: 导航链接悬停样式

效果预览

💡 所有导航区域的链接都有统一的悬停效果

/* 为所有导航相关区域的链接设置统一样式 */
:is(nav, .menu, .breadcrumb) a:hover {
  background: var(--primary);
  color: white;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(16, 185, 129, 0.3);
}

:is(nav, .menu, .breadcrumb) a:active {
  transform: translateY(0);
}

/* 如果不用 :is(),需要写 6 个选择器(3个容器 × 2个状态) */

场景 2: 表单元素统一样式

效果预览

💡 所有输入元素都有统一的样式和交互效果

/* 为所有输入类元素设置统一的基础样式 */
:is(input[type="text"], 
    input[type="email"], 
    input[type="password"], 
    textarea, 
    select) {
  width: 100%;
  padding: 10px 12px;
  border: 2px solid var(--border-color);
  border-radius: 6px;
  transition: all 0.3s;
}

/* 统一的焦点样式 */
:is(input[type="text"], 
    input[type="email"], 
    input[type="password"], 
    textarea, 
    select):focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
}

/* 如果不用 :is(),需要重复写 5 次每个规则 */

场景 3: 多区域标题样式

效果预览

文章标题

这是文章区域的内容。所有标题都有统一的样式。

文章小节

小节内容也遵循相同的样式规则。

💡 不同区域的标题都有统一的视觉风格

/* 为多个区域的标题设置统一样式 */
:is(.article-section, .sidebar-section, .footer-section) :is(h2, h3) {
  color: #1f2937;
  margin: 0 0 12px 0;
  padding-bottom: 8px;
  border-bottom: 3px solid rgba(0, 0, 0, 0.2);
  font-weight: 700;
}

/* 添加装饰性前缀 */
:is(.article-section, .sidebar-section, .footer-section) :is(h2, h3)::before {
  content: "▸ ";
  color: #7c3aed;
  font-weight: 900;
}

/* 两个 :is() 组合:3个区域 × 2个标题 = 6个选择器
   如果不用 :is(),需要写 12 个选择器(6个基础 + 6个伪元素) */

浏览器兼容性

:is() 伪类在现代浏览器中得到了广泛支持:

浏览器 支持版本 状态
Chrome / Edge 88+
Firefox 78+
Safari 14+
Opera 74+
💡 历史说明

:is() 最初被称为 :matches():any()。 如果需要支持旧版浏览器,可以使用传统的选择器列表作为降级方案。

查看详细兼容性数据 →