根本原因是浏览器不识别:has()语法,safari 15.4前、firefox 120及更早、electron内核低于chromium 105时整条规则被静默忽略,且.card:has(img)仅检测标签存在性,无法响应加载失败状态。

为什么直接写 .card:has(img) .text { width: 100%; } 有时不生效
根本原因不是选择器写错了,而是浏览器根本不识别该规则——Safari 15.4 之前、Firefox 120 及更早、Electron 内核低于 Chromium 105 的环境里,:has() 会被静默忽略,DevTools Styles 面板里都看不到这条规则。更隐蔽的问题是:.card:has(img) 只检测 <img> 标签是否存在于 DOM 中,哪怕 src="" 或 src="404.jpg",它也匹配。如果你实际想响应“图片加载失败”,:has() 本身做不到。
.card:has(img) 和 .card:not(:has(img)) 的真实适用场景
这两个组合是目前唯一稳定可用的判断逻辑,适用于纯结构层面的样式切换:
-
.card:has(img) .text→ 有<img>标签时,文字容器宽度收窄(比如设为width: 70%),留出图片空间 -
.card:not(:has(img)) .text→ DOM 中完全没写<img>时,文字撑满卡片(width: 100%),避免空白 - 注意:不要用
:has(img:loaded)——它尚未被任何浏览器实现,写了整条 CSS 规则会失效 - 如果需要区分“加载失败”,必须由 JS 主动添加 class(如
img.error),再写.card:has(.error)
文字宽度调整必须作用于容器,而不是文本节点本身
常见错误是直接给 <p></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/code/12093" title="CSS婚礼策划服务机构宣传网站模板"><img
src="https://img.php.cn/upload/webcode/000/000/018/178607072210981.jpg" alt="CSS婚礼策划服务机构宣传网站模板" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/code/12093" title="CSS婚礼策划服务机构宣传网站模板" class="overflowclass">CSS婚礼策划服务机构宣传网站模板</a>
<p class="overflowclass">CSS婚礼策划服务机构宣传网站模板是一款适合提供婚礼策划和婚庆服务机构宣传网站模板下载。提示:本模板调用到谷歌字体库,可能会出现页面打开比较缓慢。</p>
</div>
<a rel="nofollow" href="/xiazai/code/12093" title="CSS婚礼策划服务机构宣传网站模板" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div> 或 <span></span> 设 width,但行内元素对 width 不响应。正确做法是把文字包在一个块级容器里(如 <div class="text">),再对这个容器设宽:
<pre class="brush:php;toolbar:false;">.card .text {
display: block;
}
.card:has(img) .text {
width: 65%;
}
.card:not(:has(img)) .text {
width: 100%;
}</pre>
<p>另外,<code>max-width 比 width 更安全,尤其在响应式布局中;若卡片本身用 flex 或 grid 布局,优先考虑 flex: 1 或 grid-column 控制占比,而非硬设像素或百分比。
Safari 15.4–16.3 的兄弟选择器陷阱
如果你试图用 .card:has(img + .text) 这类带 + 的写法,在 Safari 15.4 到 16.3 之间大概率静默失效——它不报错,但样式就是不应用。稳妥方案是放弃兄弟关系依赖,回归最简结构:
- 确保
<img>和文字容器是同级子元素 - 用
.card:has(img) .text直接后代选择,兼容性最好 - 避免嵌套
:has()(如:has(:has(img))),所有浏览器都不支持 - 不要在
@media或@supports里包裹:has()规则,旧版 Safari 会直接跳过
真正容易被忽略的是 DOM 节点类型干扰:注释、空格文本节点会让 :nth-child() 类选择器偏移,但 :has(img) 不受此影响——只要 <img> 标签在 HTML 里,它就匹配,这点反而比计数类用法更鲁棒。










