[attr*="value"]是唯一能匹配任意位置子串的写法,它执行纯字符串包含判断,只要属性值中连续出现指定字符序列即命中,不区分单词边界、不切分空格、对大小写敏感。

[attr*="value"] 是唯一能匹配任意位置子串的写法
它不是“模糊匹配”,而是纯字符串包含判断:只要属性值里连续出现指定字符序列,就命中。比如 [class*="error"] 会选中 class="form-error"、class="has-error-message",甚至 class="success"(不含)——但注意,"success" 不含 "error",所以不会被选中。
常见误用是把它当“类名包含”用,结果误伤:[class*="col"] 会同时匹配 class="col-12" 和 class="social-link",因为后者含 "col" 连续子串。
- 对大小写敏感:
[href*="EXAMPLE"]不匹配href="https://example.com" - 不区分单词边界,也不做空格切分 —— 它只扫原始字符串
- 无法跳过 HTML 实体或 URL 编码,
[src*="logo&size=big"]不会匹配src="logo&size=big"(实际解析后是logo&size=big),得写成[src*="logo&size=big"]或提前 decode
为什么 [class*="xxx"] 经常选错元素
因为 class 属性在 DOM 中是空格分隔的字符串,而 *= 对整个字符串做扫描,不是对每个类名单独比对。例如:class="btn-primary disabled" 的原始值是 "btn-primary disabled",[class*="dis"] 能命中,但 [class*="btn"] 同样会命中 class="sub-btn-icon" —— 这不是 bug,是设计如此。
真正想匹配“独立类名”,该用 [class~="btn"];想匹配“以 btn 开头的类名”,CSS 没原生支持,得靠 JS 提取 classList 后过滤。
-
[class*="btn"]✅ 匹配class="btn"、class="btn-lg"、class="primary-btn" -
[class*="btn"]❌ 不匹配class="button"(不含"btn"连续子串) - 若 HTML 中 class 值含不可见字符(如 BOM、零宽空格),
*=会静默失败 —— DevTools 里看不出,但 computed style 不生效
替代方案:什么时候不该用 *=
当目标明确是“某个类存在”时,[class~="xxx"] 更安全;当要匹配文件扩展名、协议前缀等结构化字符串时,^= 或 $= 更精准。滥用 *= 容易导致样式泄漏,尤其在第三方组件或遗留 HTML 中。
-
[href*="login"]可能误中href="/logout?redirect=login"—— 改用[href^="/login"]或[href$="/login"]更可控 -
[data-id*="user"]会匹配data-id="admin-user-123"和data-id="superuser",如果只想要前缀,必须写[data-id^="user-"] - 组合
:not()可缓解误匹配,但嵌套层级一深就难调试,比如[class*="modal"]:not([class*="backdrop"]):not([class*="fade"])
真实场景下的性能与可维护性提醒
*= 在现代浏览器中没有明显性能开销,但它会让 CSS 逻辑依赖 HTML 字符串细节 —— 类名拼写、顺序、连字符位置稍有变动,样式就失效。比起靠选择器“猜”结构,更推荐在关键节点加语义化 data- 属性,比如把 class="status-pending" 改成 data-status="pending",再用 [data-status="pending"] 精确控制。
最易被忽略的是不可见字符和大小写混合场景:一个从 CMS 输出的 class 值若带 BOM 或换行符,*= 就完全失效,且无报错提示 —— 这类问题只能靠 JS 预处理或手动 inspect 元素属性面板确认原始值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











