:has(img) 仅检测 dom 中是否存在 标签,与图片是否加载完成无关;它适用于“有图/无图”的布局分支,不适用于加载状态反馈,需配合 js 处理错误或加载完成场景。

为什么直接写 :has(img) 就能切换布局,而不是等图片加载完
:has(img) 只看 DOM 里有没有 <img> 标签,不管它 src 是否有效、是否加载中、是否 404。只要 HTML 里写了 <img src="xxx">,哪怕路径是空的或错的,这条规则就生效。所以它不是“图片加载完成才触发”,而是“结构存在即响应”。这决定了它适合做“有图/无图”的基础布局分支,不适合做“加载失败/成功”的状态反馈。
.card:has(img) 和 .card:not(:has(img)) 的实际写法差异
别用 class 切换来模拟这种逻辑——那是倒退。真实写法就是两条纯 CSS 规则:
-
.card:has(img)→ 启用 flex 或 grid 布局,设图片区域高度,加 gap,让文字对齐居中 -
.card:not(:has(img))→ 回退为 block 布局,去掉图片相关 padding/margin,文字垂直流自然展开
注意:不能写成 .card:has(img) .card-content 去单独调文字样式——要改的是整个 .card 的 display 和内部结构。否则在 Safari 15.4+ 里可能因解析顺序出错。
容易被忽略的兼容性断点和降级行为
截至 2026 年中,Chrome 105+、Safari 15.4+、Firefox 121+ 原生支持;Edge 同 Chrome。不支持时整条 :has() 规则被浏览器忽略,.card 会按默认样式渲染(比如你没写 fallback 规则,它就按浏览器初始值显示)。这意味着:
- 别依赖
:has()做关键视觉结构,比如把文字藏在display: none里等着它显出来——不支持时文字直接消失 - 写 fallback 时,优先保证
.card在无 :has 支持下仍有可用排版(比如设个默认display: block) -
:has(img:loaded)仍是草案,所有浏览器都不认,写了等于废掉整条规则
和图片加载失败场景共存时该怎么办
:has() 不感知网络状态,所以 src 404 或跨域报错时,它照样匹配 :has(img)。真要区分“有标签但加载失败”,必须配合 JS:
- 监听
img.onerror,给父.card加 class,比如.card.img-error - 再写
.card.img-error:has(img)或.card:has(img.img-error)做二次样式覆盖 - 纯 CSS 搞不定这个层级,硬上只会让布局在不同加载阶段反复抖动
真正要小心的不是怎么写 :has(),而是它只解决“结构存在”这一层——后面所有加载、错误、懒加载时机,都得靠 JS 补位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











