你还在给每个图片父元素加类名?CSS :has() 让选择器“逆天改命”
你还在给每个图片父元素加类名CSS :has() 让选择器“逆天改命”引言“组长这个需求我写不了。”“什么需求”“产品经理说所有包含图片的卡片要在卡片上加一个‘带图标识’的边框。但是这些卡片是动态渲染的图片可有可无我总不能每个卡片都写个条件判断吧”组长瞥了我一眼“你用 CSS 啊。”“CSS 怎么选CSS 又没办法判断一个元素里有没有图片……”组长微微一笑“那是以前的 CSS 了。你知道:has()吗它能让父元素根据子元素的状态来改变自己。简单来说就是‘子凭父贵’的反过来——父凭子贵。”我当时一脸懵还有这种操作那天下午我学会了:has()然后发现——原来 CSS 早就不是当年的 CSS 了。它悄悄给自己装了个“逆向思维”的外挂只是我们都不知道。一、:has() 是什么CSS 的“时光倒流”在 CSS 选择器的历史上我们一直只能从上往下选父元素 → 子元素兄弟元素 → 相邻兄弟。比如div p选择 div 里的所有 ph1 p选择紧跟在 h1 后面的 p。但从来没有人能根据子元素的状态来选择父元素。直到:has()出现。:has()是一个关系伪类它允许你根据元素的后代或后续兄弟元素来匹配该元素。语法看起来就像是在问“嘿这个元素里面有没有符合某个条件的子元素”/* 选择所有包含 img 元素的 figure */figure:has(img){border:2px solid gold;}/* 选择所有包含 .error-message 的表单 */form:has(.error-message){border:1px solid red;background-color:#ffeeee;}更妙的是:has()里面可以写几乎任何复杂选择器包括伪类、组合器甚至可以嵌套:has()。二、实战那些让你拍大腿的场景2.1 场景一包含图片的卡片加特殊样式终于不用 JS 了divclasscardh3标题/h3p一些文字.../pimgsrcphoto.jpgalt配图/divdivclasscardh3标题/h3p没有图片的卡片/p/div.card:has(img){box-shadow:0 4px 12pxrgba(0,0,0,0.1);border-left:4px solid #ff8800;}只有带图片的卡片才会获得橙色左边框干净利落。2.2 场景二表单实时校验反馈不用 JS 监听/* 如果有无效输入框给表单加个红框 */form:has(input:invalid){border:2px solid red;padding:10px;}/* 如果有被选中的复选框给父级加个标记 */fieldset:has(input[typecheckbox]:checked){background-color:#e0ffe0;}这比以前用 JS 监听每个 input 然后给父级加类名优雅太多。2.3 场景三空状态提示/* 如果列表里没有 li显示空状态提示 */ul:not(:has(li))::after{content:暂无数据;display:block;color:#999;text-align:center;}:not(:has(...))这个组合很有用表示“没有子元素满足条件”。2.4 场景四兄弟元素的影响:has()不仅可以选祖先还可以选兄弟/* 如果 h2 后面紧跟着 p给 h2 加下划线 */h2:has( p){text-decoration:underline;}这利用了组合器 p表示“后面紧邻的 p”所以h2:has( p)就是“后面有 p 的 h2”。实际上:has()里的选择器可以往后看。2.5 场景五多级嵌套的“父选择”/* 如果某个 section 里有一个 article且 article 内有 img给 section 加背景 */section:has(article:has(img)){background:#fafafa;}这就是嵌套:has()越看越像 XPath但威力巨大。三、:has() 的“阴暗面”性能与兼容这么强大的东西有没有什么坑3.1 兼容性:has()是CSS 选择器 Level 4的一部分。它在Chrome 105、Edge 105、Firefox 121、Safari 15.4开始支持。也就是说2023 年以后的主流浏览器基本都能用。但对于老浏览器需要做降级处理比如用 JS 回退。3.2 性能考虑:has()被称为“昂贵的选择器”因为它需要检查元素的后代或后续兄弟浏览器可能需要做更多工作。但现代浏览器已经做了大量优化在合理使用下不会明显影响性能。不要滥用比如不要给每个元素都加上:has(*)这种通配。最佳实践尽量限定范围比如nav:has( a.active)比*:has(a)高效得多。3.3 一些你不能做或不应做的事不能在:has()里使用:has()自身形成循环引用理论上可以但你会把自己绕晕。不能用:has()选择祖先的祖先它可以但性能会下降。不能用:has()来改变页面结构它只是选择器只能应用样式不能添加或删除元素。四、还有哪些“逆天”的新选择器与:has()同期或稍早CSS 还引入了:where()优先级为 0用于降低选择器权重。:is()可以写一组选择器比如:is(header, main, footer) p。:not()也升级了可以接受复杂选择器列表。scope实验性功能可以限定样式的作用域。这些新特性正在把 CSS 从“声明式样式表”变成“轻量级逻辑引擎”。五、总结CSS 不再是“语言残疾”以前我们常开玩笑说“CSS 不是编程语言。”现在有了:has()CSS 居然能根据子元素来决定父元素样式这几乎就是一种“条件判断”能力。:has()的出现让我们可以少写很多 JavaScript 类名操作让样式更纯粹、更内聚。虽然兼容性还没到 100%但已经值得我们在现代项目中尝试。下次产品经理再提“根据子元素内容改变父元素样式”的需求你可以自信地说“交给 CSS不用写 JS。”每日一问你还遇到过哪些用 JS 实现很麻烦但 CSS 新特性可以轻松解决的问题评论区分享一起刷新认知
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2455893.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!