CSS3选择器笔记

CSS3选择器笔记

参考资料:

一、基础选择器

  1. 通配符选择器 * 选择所有元素
  2. 元素选择器 element 选择所有<element>元素
  3. ID选择器 #id 选择指定id的元素
  4. 类选择器 .class 选择指定class的元素
  5. element.classp.hometown选择所有class="hometown"的p元素

二、复合选择器

  1. 并集/群组选择器 selector1,..,selectorN 用逗号隔开
  2. 后代/包含选择器 祖先selector 后代selector 用空格隔开
  3. 子代选择器 父selector>子selector 用>隔开。如div>p表示选择所有父级是div 元素的p元素
  4. 兄弟选择器
    • 相邻兄弟 selector1+selector2 用+隔开。如div+p 表示选择所有紧跟在div元素之后的第一个p元素。即同级第一个弟弟。
    • selector1~selector2 用~隔开。如div~p表示选择div元素之后的所有p元素。即同级所有弟弟。

三、属性选择器

  1. [attr][target]表示选择所有带有target属性元素
  2. [attr=value][target=_black]表示选择所有使用target="_blank"的元素
  3. [attr~=value] 如[title~=flower]表示选择标题属性包含单词"flower"的所有元素。注意值为整个单词。
  4. [attr*=value][title*=flow]表示选择标题属性包含字符串"flow"的所有元素。注意是值为包含的子字符串。
  5. [attr|=value] 匹配属性值attr等于value,或以value-开头的元素。如[lang|=en]匹配lang="en"lang="en-US",不匹配lang="enUs"lang="en zh"
  6. [attr^=value] 匹配属性值attr以value开头的元素。如[src^=https]表示选择所有src属性的值以"https"开头的元素
  7. [attr$=value] 匹配属性值attr以value结尾的元素。如[src$=".pdf"]表示选择所有src属性的值以".pdf"结尾的元素。

通常情况下,属性选择器中的属性值不需要引号,但当属性值包含特殊字符或空格时就需要加引号。

四、伪类选择器(Pseudo-classes)

伪类选择器用来选择DOM元素在特定状态下的样式.这些特定状态并不是由文档结构决定的,而是由用户行为(如点击、悬停)或元素的状态(如被访问、被禁用)来定义的。

伪类选择器作用于实际存在的元素,不直接改变元素的结构,而是影响元素在特定条件下的表现样式。

语法: selector:pseudo-class { property: value; }

伪类可以在同一选择器中组合使用,如 a:hover:focus 表示同时处于悬停和聚焦状态的a

(一)动态伪类:描述用户与元素的交互状态

  1. a:link 用于选择尚未被用户访问过的<a>元素超链接
  2. a:visited 用于选择用户已经访问过的链接
  3. :hover 当鼠标悬浮在元素上时触发
  4. :active 用于表示用户正在激活或按下某个元素
  5. :focus 用于选择获得焦点的元素,常用于表单控件或可聚焦元素

注意:<a>样式设置顺序为:link→:visited→:hover→:active,否则会失效。记忆口诀:love hate 爱恨准则。

(二)结构性伪类:根据元素在文档结构中的位置来选择元素

  1. :root 选择文档的根元素,HTML文档通常是<html>
  2. :empty 选择没有任何子级(包括文本节点)的元素
  3. :first-child/:last-child/:only-child/:nth-child(n)/:nth-last-child(n) 选择父元素的第一个/最后一个/唯一一个/第n个/倒数第n个子元素,其中n可以是关键字odd(奇数)和even(偶数),也可以是公式an+β(如4n+1)
  4. :first-of-type/:last-of-type/:only-of-type/:nth-of-type(n)/ nth-last-of-type(n):first-child等相似,区别在于first-child是结构上的紧跟着的第一个子元素,而first-of-type不要求子元素紧跟在父元素下,只要是同类型中的第一个就可以了。

理解:first-child:first-of-type的区别

<div>
    <p>第一个子元素</p>
    <h1>第二个子元素</h1>
    <span>第三个子元素</span>
    <span>第四个子元素</span>
</div>
  • p:first-child 匹配到的是p元素,因为p元素是div的第一个子元素;
  • h1:first-child 匹配不到任何元素,因为在这里h1是div的第二个子元素,而不是第一个;
  • span:first-child 匹配不到任何元素,因为在这里两个span元素都不是div的第一个子元素;
  • p:first-of-type 匹配到的是p元素,因为p是div的所有类型为p的子元素中的第一个;
  • h1:first-of-type 匹配到的是h1元素,因为h1是div的所有类型为h1的子元素中的第一个;
  • span:first-of-type 匹配到的是第三个子元素span。这里div有两个为span的子元素,匹配到的是它们中的第一个。

(三)UI元素状态伪类:描述元素在用户界面中的状态

  1. :enabled:disabled 用于表单元素是否可用
  2. :checked 用于表示单选框或复选框是否被选
  3. :out-of-range/:in-range 匹配值在指定区间之外/内的input元素
  4. :read-write/:read-only 匹配可读写/设置"readonly"(只读)属性的元素,主要用于input和textarea
  5. :optional/:required 匹配可选/设置了"required"属性的表单元素(input、select、textarea)
  6. :valid/:invalid 匹配输入值为合法/非法的元素,如input的min和max、email字段、合法的数字字段等

(四)逻辑伪类

1. :not()

:not(selectors) 匹配不符合一组选择器的元素,作用是防止特定的元素被选中。注意:

  • 可以利用:not()提高规则的优先级。如#foo#foo:not(#bar)都将匹配相同元素,但后者优先级(权重)更高。
  • :not()优先级将由其逗号分割的参数中优先级最高的选择器指定。
  • 如果传递给:not()的选择器无效或浏览器不支持,则整个规则都将是无效的。
  • :not(.foo)将匹配任何非.foo元素,包括html和body。
2. :has()

parent:has(selector){} 根据其后代元素来选择一个元素。

  • parent: 父元素的选择器。样式将作用在该元素上。
  • selector: 希望在父元素中找到的子元素的选择器。起到匹配父元素的作用。

注意::has()不能和*选择器一起使用,只能与类型选择器(如div、span等)或类选择器一起使用。

ul:has(li):has(div){} 表示选择同时包含li和div子元素的ul元素。

3. :is()

:is(selector1,...,selectorN){} 接收任意数量的选择器作为参数,并且返回这些选择器匹配的元素的并集。注意:is()不能选择伪元素。

:is()大幅度缩减了选择器列表的字符数,简化了选择器列表的复杂度,降低了书写选择器列表出错的概率。

:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6)  {
    color: red;  
}

等价于

section h1, section h2, section h3, section h4, section h5, section h6,
article h1, article h2, article h3, article h4, article h5, article h6, 
aside h1, aside h2, aside h3, aside h4, aside h5, aside h6, 
nav h1, nav h2, nav h3, nav h4, nav h5, nav h6  {  
    color: red;  
}

:is()的优先级取决于其参数列表中优先级最高的选择器。 因此,使用:is()可能会提升选择器的优先级。

例如:

:is(ol, .list, ul) li  {  
    color: red;
}

ol li  { 
    color:green;
}

按照就近原则,ol li字体颜色应该为green,但是:is()参数中有优先级更高的.list,导致:is(ol) li{...}的优先级高于ol li。因此,最终ol li的字体颜色是red。

:is()可以避免选择器列表失效。 通常选择器列表包含一个或者多个无效选择器,将导致整个选择器列表失效。:is()伪类函数可以避免这个问题。:unsupported是无效选择器,未使用:is()的选择器列表将失效被忽略;而使用:is()会忽略掉无效选择器,其他选择器依然有效。

<section>
  <h1>内容测试</h1>
</section>
<article>
  <h1>内容测试</h1>
</article>

选择器有效,字体颜色为red

:is(section, article,:unsupported) h1{
  color:red;
}

选择器列表整体失效,字体颜色color:red未生效

section h1, article h1,:unsupported{
    color:red;
}
4. :where()

:where(selector1,...,selectorN)的功能和用法与:is()完全一致。唯一的区别是:where()的优先级始终是0。

下面这个例子最终字体颜色为blue

/**优先级权重为0**/
:where(ol,.list, ul) li  {  
    color: red;
}

/**优先级权重为 1+1=2**/
ol li {
    color:blue;
}

/**优先级权重为1**/
li { 
    color:green;
}

(五)其它伪类

  1. :lang(<language-code>[,<language-code>]*) { } 向带有lang属性的元素添加样式。language-code是整个单词,如en或en-US。支持多个值。
  2. :target用于当前活动的target元素的样式,与锚点链接使用。
    <a href="#first">1</a><a href="#second">2</a>
    <pid="first">第-页</p ><pid="second">第二页</p 
    
    p:target { background: red;}
    

五、伪元素选择器(Pseudo-elements)

伪元素选择器用于创建并选择元素内的某个特定部分或是在元素前后生成新的、虚拟的内容节点。

CSS3伪元素选择器允许开发者在不修改HTML结构的前提下,通过CSS为元素添加或修改特定部分的样式,或在元素内部或外部生成并控制虚拟内容。

CSS3用单冒号:标识伪类,用双冒号:标识伪元素。

伪元素由于代表了元素内部的特定部分或生成的新内容,一般不能在同一选择器中重复出现,一个元素在同一时刻只能有一个::before或::after伪元素生效,即p::before::after无效。

  1. ::first-letter 用于设置元素内首字母的样式
  2. ::first-line 用于设置元素内首行文本的样式
  3. ::selection匹配元素中被用户选中或处于高亮状态的部分。::selection只可以应用于少数的CSS属性:color、background、cursor、outline。
  4. ::before::after伪元素分别在所选元素的内容区域之前/后创建一个新的、无内容、不可见的“子元素”。然后,通过给这个伪元素设置样式(如内客、尺寸、颜色、背景等),使其变为可见,并在视觉上表现为紧随原元素内容之前/后的部分。这些内容由content属性定义,并且可以应用其他样式。::before创建的是行内元素,权重为1,无法通过JS进行DOM操作。

语法:selector::before {content: <内容值>; /*其它样式声明*/}

content属性是定义伪元素生成内容的关键。可选值为:

  • none:设置content为空值。
  • normal:在 ::before 和 ::after 中会被视为none,即也是空值。
  • 字符串string:直接指定要显示的文本内容。
  • open-quote|close-quote:设置前/后引号。
  • no-open-quote|no-close-quote:移除内容的开始/闭合引号。
  • url(url):设置某种多媒体的链接地址。如li::before { content: url(icon-file,svg); }
  • attr(attribute):将元素的attribute属性以字符串形式返回。
  • counter(name[, style ]*):设定计数器,实现对多个项目连续编号。style值同list -style-type,默认为阿拉伯数字。
  • counters(name, strings[, style ]*):用来处理嵌套计数器子序号的连接字符串。

content使用示例

1. 清除浮动
<!--css-->
.left {float: left}
.right {float: right}
.clear:after {
    content: '';
    clear: both;
    display: block;
}

<!--html-->
<div class="container clear">
    <div class="left">左</div>
    <div class="right">右</div>
</div>

父元素.container中两个子元素.left和.right浮动后会脱离文档流,无法撑起容器,造成.container高度为0。使用伪元素:after清除浮动,三个属性缺一不可:

  • content: ‘’;通过:after添加一个内容为空的伪元素。
  • clear: both;伪元素:after两侧浮动清除。
  • display: block;设置块元素,因为clear只对块元素有效。
2. 小三角的气泡窗口
<!--css-->
.box {
    width: 200px;
    height: 100px;
    border-radius: 5px;
    background: #fff;
    position: relative;
}
.box:after {
    content: '';
    position: absolute;
    bottom: -20px;
    right: 20px;
    width: 0;
    height: 0;
    border-top: 10px solid #fff;
    border-bottom: 10px solid transparent;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
}

<!--html-->
<div class="box"></div>

效果:

配合伪元素:after,实现了一个右下角带倒三角指向性的气泡窗口。通过调整border各边的颜色和绝对定位位置,可以绘制出指向不同的气泡窗口。

3.面包屑菜单
<!--css-->
ul li {
    display: inline-block;
    font-weight: bold;
}

ul li:not(:last-child):after {
    content: '\276D';
    margin: 5px;
}

<!--html-->
<ul>
    <li>首页</li>
    <li>商品</li>
    <li>详情</li>
</ul>

效果:

4. 加载中…动画
<!--css-->
.loading:after {
    content: ".";
    animation: loading 2s ease infinite;
}

@keyframes loading {
    33% {
        content: "..";
    }
    66% {
        content: "...";
    }
}

<!--html-->
<p class="loading">加载中 </p>

效果:

5. attr属性内容生成
<!--css-->
.web:after {
    content: "("attr(href)")"
}

<!--html-->
<a class="web" href="https://echeverra.cn">echevera</a>

效果:

content值也可以是attr()方法,用来获取指定属性的值,可插入到指定的位置。

6. 半边特效
<!--css-->
span{
    font-family: sans-serif;
    font-size: 30px;
    font-weight: bold;
    position: relative;
    color: green;
}
span:before{
    content: attr(text);
    color: orange;
    position: absolute;
    left: 0;
    top: 0;
    width: 50%;
    overflow: hidden;
}

<!--html-->
<span text="echeverra">echeverra</span>
<span text="博">博</span>
<span text="客">客</span>

效果:

半边特效是通过attr()方法获取text属性值,属性值与其内容相同,巧妙的设置绝对定位,只显示一半并覆盖了原文本内容,实现文字半边特效。

7. 添加章节数
<!--css-->
ul{
    counter-reset: section;
}
li{
    list-style-type: none;
    counter-increment: section;
}
li:before{
    content: counters(section, '-') '.';
}

<!--html-->
<ul>
    <li>章节一</li>
    <li>章节二
        <ul>
            <li>章节二一</li>
            <li>章节二二</li>
            <li>章节二三</li>
        </ul>
    </li>
    <li>章节三</li>
    <li>章节四</li>
    <li>章节五
        <ul>
            <li>章节五一</li>
            <li>章节五二</li>
        </ul>
    </li>
    <li>章节六</li>
</ul>

效果:

这里用到了counter计数器方法,涉及到counter-reset、counter-increment、counter()和counters()几个属性。

  • counter-reset用来指定计数器名称,例子中命名为section,同时可以指定计数器开始计数的数值,如指定开始计数数值为1:counter-reset: section 1;,不指定默认为0。
  • counter-increment用来指定计数器每次递增的值,如指定计数器递增值为2:counter-increment: section 2;,默认值为1,counter-increment只要指定了counter-reset,对应的计数器的值就会变化。
  • counter(name, style)用来输出计数器的值。其中name为计数器名称,style可选参数,默认为阿拉伯数字,也可指定list-style-type支持的值,如罗马数字lower-roman。
  • counters(name, strings, style)用来处理嵌套计数器,同样是输出计数器的值,和counter()不同的是多了一个strings参数,表示子序号的连接字符串。例如1.1的string就是’.‘,1-1就是’-'。
8. 对部分和子部分进行编号
<body>
<h1>HTML 教程:</h1>
<h2>HTML 教程</h2>
<h2>CSS 教程</h2>

<h1>Scripting 教程:</h1>
<h2>JavaScript</h2>
<h2>VBScript</h2>

<h1>XML 教程:</h1>
<h2>XML</h2>
<h2>XSL</h2>
</body>

body {
  counter-reset: section;
}

h1 {
  counter-reset: subsection;
}

h1::before {
  counter-increment: section;
  content: "Section " counter(section) ". ";
}

h2::before {
  counter-increment: subsection;
  content: counter(section) "." counter(subsection) " ";
}

效果:

在这里插入图片描述

9. 计算checkbox选中数
<!--css-->
form {
    counter-reset: count 0;
}

input[type="checkbox"]:checked {
    counter-increment: count 1;
}

.result:after {
    content: counter(count);
}

<!--html-->
<form>
    <input type="checkbox" id="javaScript">
    <label for="javaScript">javaScript</label>
    <input type="checkbox" id="PHP">
    <label for="PHP">PHP</label>
    <input type="checkbox" id="Python">
    <label for="Python">Python</label>

    <div class="result">已选:</div>
</form>

效果:

巧妙运用计数器配合:checked伪类,选中计数器增加1,取消选中减1,用CSS实现动态计数功能。