百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

非常强大的 CSS 选择器 :has()

myzbx 2025-01-17 12:23 50 浏览

大家好,我是 Echa。

前一段时间,小编我陆陆续续分享了关于CSS相关的干货文章,有兴趣的粉丝们一起来回顾一下相关知识,每一篇都有对应的知识点:

一文读懂 CSS 单位

图解 CSS Grid 布局

Chrome 108 发布新的 CSS 布局单位升级

几行代码实现网站变灰效果

现代CSS样式重置最佳实践

优化 CSS 代码的12个小技巧

你有没有想过使用CSS选择器来检查父元素中是否存在特定的元素?例如,如果一个卡片组件中有图片,就给它添加一个display:flex。这以前在CSS中是无法实现的,而全新的 CSS 选择器:has就可以帮助我们选择包含特定元素的父元素。下面来看看这个全新的 CSS 选择器吧!

:has 选择器概述

在CSS中,我们无法根据元素中是否存在特定的元素来设置父元素的样式,要想实现这一点,就必须创建CSS类,并根据需要进行类的切换。来看下面的例子:

这里有两种卡片:包含图片和不包含图片。在CSS中需要这样做:

/* 有图片的卡片 */
.card {
  display: flex;
  align-items: center;
  gap: 1rem;
}

/* 没有图片的卡片 */
.card-plain {
  display: block;
  border-top: 3px solid #7c93e9;
}
<!-- 有图片的卡片 -->
<div class="card">
  <div class="card-image">
    <img src="awameh.jpg" alt="">
  </div>
  <div class="card-content">
    卡片内容
  </div>
</div>

<!-- 没有图片的卡片 -->
<div class="card card-plain">
  <div class="card-content">
    卡片内容
  </div>
</div>

这里创建了一个类card-plain,专门用于没有图片的卡片,在没有图片时就不需要flex布局。如果使用 CSS 中的父选择器 :has 就不需要再写这个类,只需要使用它来检查卡片中是否包含.card-image即可:

.card:has(.card-image) {
  display: flex;
  align-items: center;
}

根据 CSS 规范,:has 选择器可以检查父元素是否包含至少一个元素,或者一个条件,例如输入是否获取到焦点。

:has 选择器不仅可以检查父元素是否包含特定的子元素,还可以检查一个元素后面是否跟有另一个元素:

.card h2:has(+ p) { }

这将检查 <h2> 元素是否直接跟在 <p> 元素之后。

我们也可以将它与表单元素一起使用来检查输入是否获取到了焦点:

form:has(input:focused) {
    background-color: lightgrey;
}

:has 选择器使用示例

下面来看看一些使用:has选择器实现页面效果的案例吧!

1. 标题样式

当处理章节标题时有两种情况,一种是只包含标题,另一种包含标题和链接。

根据是否有链接来定义不同的样式:

<section>
  <div class="section-header">
    <h2>Latest articles</h2>
    <a href="/articles/>See all</a>
  </div>
</section>
.section-header {
  display: flex;
  justify-content: space-between;
}

.section-header:has(> a) {
  align-items: center;
  border-bottom: 1px solid;
  padding-bottom: 0.5rem;
}

这里使用了:has(> a),它表示只选择直接子元素。

2. 卡片布局

有两种类型的卡片操作:一种只有一个操作(链接),另一种具有多个操作(保存、分享等)。

当图片具有多个操作时需要给这些操作添加display: flex,可以这样来实现:

<div class="card">
    <div class="card-thumb><img src="cool.jpg"/></div>
    <div class="card-content">
        <div class="card-actions">
            <div class="start">
                <a href="#">Like</a>
                <a href="#">Save</a>
            </div>
            <div class="end">
                <a href="#">More</a>
            </div>
        </div>
    </div>
</div>
.card-actions:has(.start, .end) {
  display: flex;
  justify-content: space-between;
}

3. 卡片圆角

根据是否有图片来重置卡片组件的border-radius

.card:not(:has(img)) .card-content {
    border-top-left-radius: 12px;
    border-top-right-radius: 12px;
}

.card img {
    border-top-left-radius: 12px;
    border-top-right-radius: 12px;
}

.card-content {
    border-bottom-left-radius: 12px;
    border-bottom-right-radius: 12px;
}

实现效果如下:

4. 过滤组件

有一个具有多个选项的组件,当它们没有被选中时,不显示重置按钮。当选中其中一个选项时,显示重置按钮。

image.png

可以使用 :has选择器轻松实现这个功能:

.btn-reset {
    display: none;
}

.multiselect:has(input:checked) .btn-reset {
    display: block;
}

5. 显示或隐藏表单元素

有时可能需要根据之前的选择来显示特定的表单字段。在下面的例子中,当下拉框选中“other”字段时,就展示 other reason 输入框:

使用 CSS :has 选择器就可以检查选择菜单是否选择了 other 字段,并在此基础上显示 other reason 输入框:

.other-field {
    display: block;
}

form:has(option[value="other"]:checked) .other-field {
    display: block;
}

6. 导航栏

有一个带有子菜单的导航栏,当鼠标悬停在菜单项上时展示子菜单:

我们需要做的就是根据是否展示子菜单来显示或隐藏右侧的箭头。可以使用:has 选择器轻松实现这一点,这里只需检查li元素中是否包含ul即可:

li:has(ul) > a:after {
    content: "";
}

7. 强制警报

在某些仪表板中,可能需要用户必须注意重要警报。在这种情况下,拥有页内警报可能还不够。例如,在这种情况下,可能会为标题元素添加红色边框和暗红色背景色。这样会增加用户快速注意到警报的可能性。

CSS :has 就可以检查.main元素是否有警报。如果有,将以下样式添加到标题中:

.main:has(.alert) .header {
    border-top: 2px solid red;
    background-color: #fff4f4;
}

8. 切换配色方案

可以使用 CSS :has 来更改网站的配色方案。例如,如果有多个使用 CSS 变量构建的主题,可以通过<select>菜单来进行切换。

html {
    --color-1: #9e7ec8;
    --color-2: #f1dceb;
}

当选择另一个主题时,CSS 变量将被更改:

html:has(option[value="blueish"]:checked) {
    --color-1: #9e7ec8;
    --color-2: #f1dceb;
}

显示效果如下:

9. 带有图标的按钮

有一个默认的按钮样式。当按钮中包含图标时,使用 flexbox 来居中对齐按钮的内容:

.button:has(.c-icon) {
    display: inline-flex;
    justify-content: center;
    align-items: center;
}

10. 多个按钮

有一组操作按钮,如果超过 2 个按钮,则最后一个按钮显示在右侧:

可以使用数量查询来实现这一点。下面的 CSS 将检查按钮的数量是否为 3 或更多。如果是,则最后一个 flex 项目将使用 margin-left: auto

.btn-group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
  
.btn-group:has(.button:nth-last-child(n + 3)) .button:last-child {
    margin-left: auto;
}

11. 根据项目数更改网格

使用 CSS grid 布局中,可以使用 minmax() 功能创建真正响应式和自动调整大小的网格项。然而,这可能还不够,我们还想根据项目数量来改变网格。

.wrapper {
    --item-size: 200px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--item-size), 1fr));
    gap: 1rem;
}

当有 5 个项目时,最后一个将换行:

可以通过检查.wrapper中是否有 5 个或更多项目来解决这个问题。同样,这是使用到了数量查询的概念。

.wrapper:has(.item:nth-last-child(n + 5)) {
    --item-size: 120px;
}

实现效果如下:

浏览器支持

:has 选择器的支持情况如下:

可以使用 CSS 中的@supports规则来判断浏览器是否支持该选择器:

@supports selector(:has(*)) {
  
}

参考:https://ishadeed.com/article/css-has-parent-selector/

相关推荐

如何设计一个优秀的电子商务产品详情页

加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...

怎么在JS中使用Ajax进行异步请求?

大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...

中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革

前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...

前端监控 SDK 开发分享_前端监控系统 开源

一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...

Ajax 会被 fetch 取代吗?Axios 怎么办?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...

前端面试题《AJAX》_前端面试ajax考点汇总

1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...

Ajax 详细介绍_ajax

1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...

6款可替代dreamweaver的工具_替代powerdesigner的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

福斯《死侍》发布新剧照 &quot;小贱贱&quot;韦德被改造前造型曝光

时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...

不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!

Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...

2025 年 Python 爬虫四大前沿技术:从异步到 AI

作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...

最贱超级英雄《死侍》来了!_死侍超燃

死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...

停止javascript的ajax请求,取消axios请求,取消reactfetch请求

一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...