CSS :has伪类
- 1 概述
- 2 实例说明
- 2.1 表单元素前面加*
- 2.2 拖拽列表
- 2.3 多层级hover
- 2.4 评星组件
- 3 兼容性
1 概述
:has()
表示满足一定条件后,就会匹配该元素。这个伪类通过把可容错相对选择器列表作为参数,提供了一种针对引用元素选择父元素或者先前的兄弟元素的方法。其语法如下:
<target>:has(<selector>)
复制
例如,下面表示选中有<p>
元素作为子元素的<section>
元素
section:has(p) { color: red }
复制
再例如,下面表示选中后面紧跟着<p>
元素的<h1>
元素:
h1:has(+p) { color: red; }
复制
:has()
也可以结合CSS:not()
伪类一起使用,例如,下面表示选中不含<p>
元素的<li>
元素:
li:not(:has(p)) { color: red; }
复制
我们还可以将多个选择器作为参数传递,下面表示选中不包含任何<p>
或<span>
元素的<li>
元素:
li:not(:has(p, span)) { color: red; }
复制
2 实例说明
2.1 表单元素前面加*
例如,在下面的表单元素中,用户名的<input>
设置了required
,表示必填项:
<form> <label>用户名</label> <input required> <label>备注</label> <input> </form>
复制
通过:has()
在必填项的前面加上红色的星号,CSS如下:
label:has(+input:required)::before { content: "*"; color: red; }
复制
选中后面紧跟着<input>
,且其为required
的<label>
元素,生成它的::before
伪元素。
2.2 拖拽列表
列表hover时出现拖拽手柄,点击拖拽手柄进行拖拽操作,HTML如下:
<div class="content"> <div class="item">列表<span class="thumb"></span></div> <div class="item">列表<span class="thumb"></span></div> <div class="item">列表<span class="thumb"></span></div> </div>
复制
列表样式CSS如下:
.content { border: 3px solid #eee; width: 300px; } .item { position: relative; padding: 10px 20px; background-color: #fff; border: 1px solid #eee; margin: 5px; }
复制
关键CSS如下:
.thumb { position: absolute; width: 30px; height: 30px; background: url("data:image/svg+xml,") center no-repeat; right: 5px; top: 0; bottom: 0; margin: auto; cursor: pointer; opacity: 0; } .item:hover .thumb { opacity: 1; } .item:has(.thumb:hover) { -webkit-user-drag: element; }
复制
首先隐藏.thumb
,当.item
触发hover时,显示.thumb
,接着使用:has()
选中触发了.thumb
hover的.item
元素,使其变为可拖拽的元素。
2.3 多层级hover
有如下所示的一个多级结构:
<div class="d1"> <div class="d2"> <div class="d3"></div> </div> </div>
复制
如果给div添加hover样式:
可以看到,当hover到里层元素时,外层元素也触发了hover样式。这有点像JS中的冒泡效果,那如何让hover的时候只触发当前的元素呢?也就是排除掉他的父级元素,:has
可以很好的解决这个问题:
div:not(:has(:hover)):hover { outline: 4px dashed red; }
复制
:has(:hover)
表示有div正处于hover,div:not(:has(:hover))
表示不选择正处于hover的div,然后为其设置hover样式。
2.4 评星组件
HTML结构如下:
<star> <input name="star" type="radio"> <input name="star" type="radio"> <input name="star" type="radio"> <input name="star" type="radio"> <input name="star" type="radio"> </star>
复制
CSS更改一下样子:
star { display: flex; } star [type="radio"] { appearance: none; width: 40px; height: 40px; margin: 0; cursor: pointer; background: #ccc; transition: .3s; -webkit-mask: url("data:image/svg+xml, ") center / 80% no-repeat; }
复制
当:hover
或者:checked
时,当前元素和当前元素之前的元素都触发选中。
star [type="radio"]:hover, star [type="radio"]:has(~:hover), star:not(:hover) [type="radio"]:checked, star:not(:hover) [type="radio"]:has(~:checked) { background: orangered; }
复制
star [type="radio"]:hover
选中当前hover的元素,star [type="radio"]:has(~:hover)
选中当前hover元素之前的元素,star:not(:hover) [type="radio"]:checked
选中当前点击的元素,star:not(:hover) [type="radio"]:has(~:checked)
选中当前点击元素之前的元素。
3 兼容性
MDN描述兼容性如下:
本文学习自:https://juejin.cn/post/7143121853853204516