[attr*="value"] 严格匹配属性值中连续包含指定子串,不解析 class 列表、无单词边界、大小写敏感;仅对单值属性(如 data-id)可靠,class 属性慎用;推荐用 :is(.a, .b) 或 data-* 属性替代。

用 [attr*="value"] 匹配属性值中包含子串的元素
这个选择器不是“模糊匹配类名”的捷径,而是严格匹配 HTML 属性值中是否**连续包含指定字符串**。它不解析 class 列表,也不做正则或通配逻辑,只做子串搜索。
常见误用场景:想选所有 class 包含 btn 的按钮,却写成 [class*="btn"] —— 这会匹配 <div class="attention">(因为 <code>"attention" 含 "ten"),也会漏掉 <button class="primary-btn large"></button>(因为 class 值是空格分隔的字符串,"btn" 前有空格,不构成连续子串)。
- 只对单值属性(如
data-id、title、src)最可靠;例如[data-id*="123"]能匹配data-id="item-123-final" - 对
class属性慎用:它把整个 class 字符串当一个整体,class="btn btn-primary"中"btn"出现在开头且后跟空格,[class*="btn"]可以命中;但class="primary-btn"也能命中,而class="btn-outline"同样命中——你控制不了前后边界 - 大小写敏感:HTML 属性值默认不区分大小写,但 CSS 选择器区分,
[data-role*="header"]不会匹配data-role="Header"
匹配类名的一部分?优先用 :is() + 多个精确类选择器
真正想按类名语义筛选(比如所有带 btn、card 或 modal 的组件),[class*="xxx"] 不够准,也不可维护。现代方案是明确列出可能的类组合:
button:is(.btn, .btn-primary, .btn-secondary),
.card:is(.card, .card-large, .card-compact),
.modal:is(.modal, .modal-fullscreen) {
border: 1px solid #ccc;
}
这比靠字符串扫描更稳定,也便于后续重构——删掉某个类名时,样式自动失效,不会残留意外匹配。
-
:is()支持逗号分隔的多个选择器,浏览器兼容性已覆盖 Chrome 100+/Firefox 100+/Safari 15.4+ - 不要试图用
[class*="btn"]替代.btn:前者无法区分btn是独立类还是其他类的子串(如"sub-btn"或"button") - 如果必须动态生成类并匹配,改用
data-属性承载语义,例如data-component="button",再用[data-component="button"]精确控制
需要真正“模糊”或“模式化”匹配?CSS 本身做不到,得靠 JS 配合
CSS 属性选择器只有 *=(包含)、^=(开头)、$=(结尾)三种字符串操作,没有正则、没有忽略空格、没有单词边界。一旦需求超出子串搜索(比如“匹配以 btn- 开头且后面跟字母数字的类”),CSS 就到头了。
- 典型场景:根据 URL 参数高亮导航项,或按数据状态切换样式(
data-status="pending|success|error")——这些适合用 JS 动态加类,再写纯 CSS 规则 - 若坚持用属性选择器,可让 JS 写入标准化的
data-值,例如把class="btn btn-lg btn-primary"对应的语义转为data-btn-size="lg" data-btn-variant="primary",再用[data-btn-variant="primary"]精确选取 - 注意:用 JS 批量操作 class 时,避免直接拼接字符串导致重复或遗漏;推荐用
element.classList.add()/toggle()等原生 API
[attr*="value"] 最稳妥的用法是配合自定义 data- 属性,而不是硬啃 class 字符串。类名是给开发者读的,不是给选择器“猜”的。











