Glittering's blog Glittering's blog
Home
  • 学习手册

    • 《JavaScript教程》
    • 《ES6 教程》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
  • 技术文档
  • 算法
  • 工作总结
  • 实用技巧
  • collect
About
  • Classification
  • Label
GitHub (opens new window)

Glitz Ma

前端开发工程师
Home
  • 学习手册

    • 《JavaScript教程》
    • 《ES6 教程》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
  • 技术文档
  • 算法
  • 工作总结
  • 实用技巧
  • collect
About
  • Classification
  • Label
GitHub (opens new window)
  • CSS

    • CSS教程和技巧收藏
    • flex布局语法
    • flex布局案例-骰子
    • flex布局案例-圣杯布局
    • flex布局案例-网格布局
    • flex布局案例-输入框布局
    • CSS3之has函数的使用
      • W3C的选择器
        • 相关的html新标签
        • :has的使用
        • 组合选择器
        • 伪类选择器
        • :target 实现模态框
        • 选择多个范围的组
        • 多个范围选择
    • CSS3之animation动画
    • CSS3之transition过渡
    • css块元素和行内元素
    • 「布局技巧」图片未加载前自动撑开元素高度
    • 文字在一行或多行时超出显示省略号
    • 字体font-weight相关知识
    • 从box-sizing属性入手,了解盒子模型
    • 水平垂直居中的几种方式-案例
    • 如何根据系统主题自动响应CSS深色模式
    • 「css技巧」使用hover和attr()定制悬浮提示
    • CSS-function汇总
    • 网格布局中的动画
  • 页面
  • CSS
mamingjuan
2025-01-10
目录

CSS3之has函数的使用

# W3C的选择器

# 相关的html新标签

figure、figcaption、pre、blockquote

<figure>
  <img src="image.png" alt="">
  <figcaption>caption and descriptions</figcaption>
</figure>


<figure>
  <figcaption>code</figcaption>
  <pre>
    function log(val) {
      console.log(val)
    }
    
    log('hello world')      
  </pre>
</figure>


<figure>
  <figcaption>Shakespeare: </figcaption>
  <blockquote>Nutrition books in the world. There is no book in life, there is no sunlight; wisdom without
    books, as if the birds do not have wings.</blockquote>
</figure>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# :has的使用

用一句话来描述: :has() 选择器是一个关系型伪类选择器,也被称为函数型伪类选择器,它和 :is()、:not() 以及 :where() 函数型选择器被称为 CSS 的逻辑组合选择器。

/* 卡片不带标题的样式规则 */
.card {
    display: flex;
    border-radius: 10px;
    max-width: 40vw;
    background-color: #F5F5F5;
}

.card img {
    display: block;
    max-width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    object-position: center;
}

/* 卡片带标题的样式规则 */
.card:has(figcaption) {
    flex-direction: column;
    gap: 1rem;
    padding: 20px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

有趣的知识:对比一下区别

section:not(:has(h1, h2, h3, h4, h5, h6))
section:has(:not(h1, h2, h3, h4, h5, h6))
1
2
  1. section:not(:has(h1, h2, h3, h4, h5, h6))

语法分析:

  • section:选择所有 section 元素。
  • :not():是一个排除伪类,它会排除符合条件的元素。
  • :has(h1, h2, h3, h4, h5, h6):表示选中那些包含 <h1> 到 <h6> 的 section 元素。

所以这个选择器的意思是:

  • 选择那些 没有包含任何 <h1> 到 <h6> 元素的 section 元素。

关键点:

  • 它选择的是 不含标题标签(即 <h1> 至 <h6>)的 section 元素。
  1. section:has(:not(h1, h2, h3, h4, h5, h6))

语法分析:

  • section:选择所有 section 元素。

  • :has():这个伪类用来选中那些包含符合特定条件的子元素的父元素。

  • :not(h1, h2, h3, h4, h5, h6):表示选中那些 不包含 <h1> 到 <h6> 元素的子元素。
    所以这个选择器的意思是:

  • 选择那些 包含至少一个不属于 <h1> 到 <h6> 的子元素 的 section 元素。

关键点:

  • 它选中的是那些**含有其他元素(非标题元素)**的 section,并不要求这些 section 内部完全没有 <h1> 到 <h6>,但是要求必须有其他非标题元素。

举个更明确的例子

<section>
  <p>This section has no headings, just a paragraph.</p>
</section>

<section>
  <h2>Title</h2>
  <p>This section has a heading.</p>
</section>

<section>
  <h1>Title</h1>
  <div>Some other content</div>
</section>

<section>
  <h1>Title</h1>
  <h3>Another Title</h3>
</section>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

第一个选择器:section:not(:has(h1, h2, h3, h4, h5, h6))

  • 会选中 第一个 section,因为它没有任何标题标签(没有 <h1> 到 <h6>)。
  • 第二个 section 被排除,因为它含有 <h2>,符合 :has() 的条件。
  • 第三个 section 被排除,因为它包含 <h1>,符合 :has() 的条件。
  • 第四个 section 被排除,因为它包含 <h1> 和 <h3>,符合 :has() 的条件。

第二个选择器:section:has(:not(h1, h2, h3, h4, h5, h6))

  • 会选中 第一个 section,因为它包含了 <p>,这是一个不是标题的元素。
  • 第二个 section 被选中,因为它有 <p>,并且 <p> 不是标题元素。
  • 第三个 section 被选中,因为它包含 <div>,而 <div> 不是标题元素。
  • 第四个 section 不会被选中,因为它只有标题元素(<h1> 和 <h3>),没有其他非标题元素。

主要区别:

  1. section:not(:has(h1, h2, h3, h4, h5, h6)):它选择的是没有包含任何标题元素的 section 元素。
  2. section:has(:not(h1, h2, h3, h4, h5, h6)):它选择的是 包含其他类型元素(非标题)的 section 元素。

总结:

  • 第一个选择器更严格,它排除了所有包含标题的 section 元素。
  • 第二个选择器则是宽松一点,它只要求 section 中必须有其他类型的元素,而不要求标题必须不存在。

# 组合选择器

“组合选择器”是一种特殊字符,表示选择器之间的关系类型。常见的组合选择器主要有:

  • 空格字符,例如 a b ,称之为后代组合选择器,匹配直接或嵌套的子元素;
  • >字符,例如 a > b ,称之为直接子元素组合选择器,仅匹配顶层未嵌套的子元素;
  • + 字符,例如 a + b ,称之为相邻兄弟组合选择器,仅匹配紧随其后的下一个兄弟元素;
  • ~字符,例如 a ~ b ,称之为通用兄弟组合选择器,匹配基础选择器(a)之后的一个或多个兄弟元素(b)。

# 伪类选择器

伪类元素使用了两个冒号 (::)而不是一个冒号 (:),这是 CSS3 规范中的一部分要求,目的是为了区分伪类和伪元素,大多数浏览器都支持下面这两种表示方式。

  • 状态伪类选择器,比如 :hover 、:active 、:visited、:target 和 :focus 等;
  • 焦点伪类选择器,比如 :focus-within 和 :focus-visible 等;
  • 结构型伪类选择器,比如 :nth-child、:nth-last-child、:first-child、 :last-child、:only-child、:nth-of-type、:nth-last-of-type、 :first-of-type、 :last-of-type 和 :only-of-type 等;
  • 表单伪类选择器,比如 :autofill、:enabled、 :disabled、:read-only、 :read-write, :placeholder-shown、:default、 :checked、:indeterminate、:valid、:invalid、:in-range、:out-of-range、:required 和 :optional 等;
  • 目标伪类选择器,比如 :target ;
  • 语言伪类选择器,比如 :dir() 和 :lang() 等;
  • 函数伪类选择器,比如 :not() 、:is() 和 :where() 等。

has的使用,另外,需要注意的是,CSS 工作组决定禁止在 :has() 内部使用所有现有的伪元素,比如 ::before 、::after、::marker 和 ::first-line 等。

/* ul 包含最多 3 个( 3 个或更少,不包括 0 ) li 项 */
ul:has(> :nth-child(-n+3):last-child) {
    border: 3px solid palegreen;
}

/* ul 包含最多 3 个( 3 个或更少,包括 0 个) li 项 */
ul:not(:has(> :nth-child(3))) {
    border: 3px solid limegreen;
}

/* ul 正好包含 5 个 li 项 */
ul:has(> :nth-child(5):last-child) {
    border: 3px solid plum;
}

/* ul 至少包含 10 个 (10 个或更多)li 项 */
ul:has(> :nth-child(10)) {
    border: 3px solid pink;
}

/* ul 包含 7 ~ 9 个 li 项*/
ul:has(> :nth-child(7)):has(> :nth-child(-n+9):last-child) {
    border: 3px solid tomato;
}
/** 不支持:has时的备选方案 */
@supports not selector(:has(works)) { 
    .card { 
        flex-direction: column; 
        align-items: flex-start; 
    } 
} 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# :target 实现模态框

<a href="#target-content" id="button">Open CSS Modal via <code>:target</code></a>
<div id="target-content">
    <a href="#" class="close"></a>
    <div id="target-inner">
        <h2>CSS Modal</h2>
    </div>
</div>
<style>
#target-content {
    pointer-events: none;
    opacity: 0;
    transition: opacity 200ms;
}
#target-content:target {
    pointer-events: all;
    opacity: 1;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 选择多个范围的组

<ul>
    <li class="rect"></li>
    <li class="rect"></li>
    <li data-range></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li data-range></li>
    <li class="star"></li>
    <li class="star"></li>
    <li class="star"></li>
    <li class="rect"></li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**选中 data-range 开始和结束之间所有 li (即所有 .circle 元素) */
[data-range] ~ :has(~ [data-range])  {
    width: 100px;
    border: 2px solid #09f;
    outline: 4px solid rgb(0 0 0 / .5);
}

/**
* [data-range]:has(~ [data-range]) 给范围起始元素(第一个设置 data-range 的 li 元素)设置样式*/
[data-range]:has(~ [data-range]) {
    background-color: #987;
    outline: 2px solid red;
}
/* [data-range] ~ [data-range] 给范围结束元素(第二个设置 data-range 的 li 元素)设置样式*/
[data-range] ~ [data-range] {
    background-color: #90f;
    outline: 2px solid orange;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 多个范围选择

<ul>
    <li data-range="start"></li>
    <li class="rect"></li>
    <li class="rect"></li>
    <li data-range="end"></li>
    <li data-range="start"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li data-range="end"></li>
    <li data-range="start"></li>
    <li class="star"></li>
    <li class="star"></li>
    <li class="star"></li>
    <li data-range="end"></li>
    <li class="rect"></li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* 选择范围组中开始和结束元素 */
[data-range] {
    box-shadow: 0 0 0 6px red;
    border-radius: 2px;
}

/* 选择范围组中起始元素 */
[data-range="start"] {
    outline:3px solid yellow;
}

/* 选择范围组中结束元素 */
[data-range="end"] {
    outline: 3px solid #e90;
}

/* 选择范围组内的第一个元素 */
[data-range="start"] + :has(~ [data-range="end"]):not([data-range]) {
    width: 80px;
    border: 4px solid #09f;
}

/* 选择范围组内的最后一个元素 */
[data-range="start"] ~ :has(+ [data-range="end"]):not([data-range]) {
     width: 80px;
     border: 4px solid;
}

/* 选择范围组内的所有元素 */
[data-range="start"] ~ :has(~ [data-range="end"]):not([data-range]) {
    width: 80px;
    border: 4px solid;
    box-shadow: 0 0 0 4px rgb(0 0 0 / .125);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
上次更新: 2025/04/07, 01:42:58
flex布局案例-输入框布局
CSS3之animation动画

← flex布局案例-输入框布局 CSS3之animation动画→

Copyright © 2015-2025 Glitz Ma
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式