CSS - 常见选择器

348 阅读14分钟

开发中经常需要找到特定的网页元素进行设置样式

所以我们需要按照一定的规则选出符合条件的元素,为之添加CSS样式

而这些规则就被称之为CSS选择器

通用选择器

通用选择器(universal selector) --- 所有的元素都会被选中

一般用来给所有元素作一些通用性的设置 --- 例如清除body默认的8px外边距

/*
  一般不建议为元素添加对应的通用选择器
  因为浏览器在使用通配符选择器为元素添加对应样式的时候
  会遍历所有的元素,并为每一个元素应用上对应的样式,包括html元素和body元素 
  有很多元素我们其实是没有使用的,但是通配符选择器还是会为他们添加对应的样式
  所以使用通配符选择器的效率比较低
*/
* {
  margin: 0;
  padding: 0;
}

/*
  如果我们需要重置某些元素的样式的时候,
  推荐显示的将我们所用到的元素逐个进行对应的清除
  或者使用normalize.css这类第三方库
*/
div,
p,
ul,
li {
  margin: 0;
  padding: 0;
}

元素选择器

元素选择器(type selectors), 使用元素的名称, 会匹配到所有符合对应元素名的元素

div {
  border: 1px solid red;
}

类选择器

.box {
  color: red;
}

可以在一个元素上添加多个类,类和类之间使用空格进行划分

<div class="foo baz bar"> Delectus reiciendis in fuga repellat reprehenderit optio, facere </div>

id选择器

#box {
  color: red;
}

Tips: 对于类选择器和id选择器

  1. 一个HTML文档里面的id值是唯一的,不能重复 --- 重复不报错 是因为浏览器做了容错处理,不推荐

  2. 不要用标签名作为id值或者类名 --- 不会报错,不推荐,可读性差

  3. id选择器名或class选择器类型如果由多个单词组成,单词之间可以用中划线-下划线_连接,也可以使用驼峰标识(包括大驼峰和小驼峰)

    • 中划线又叫连字符(hyphen)
    • 推荐使用中划线进行多个单词之间的连接符

属性选择器

/* 只要有属性title的元素,字体全部被设置为红色 */
[title] {
  color: red;
}

CSS选择器中的属性选择器可以根据元素的属性和值来选择元素。具体来说:

  1. 如果属性值是简单的单个单词,比如 lorem,引号是可以省略的。例如:

    [title=lorem] {
      color: red;
    }
    
  2. 如果属性值是复杂的,比如包含空格的字符串 lorem lorem,引号是不可以省略的。例如:

    [title='lorem lorem'] {
      color: red;
    }
    

一些其它用法

  1. 选择器 [class*=box]

    • 选择所有 class 属性值中包含 box 的元素。

    • 示例:

      <div class="dv box"></div> <!-- 符合 -->
      <div class="dv box1"></div> <!-- 符合 -->
      <div class="dv-box"></div> <!-- 符合 -->
      
  2. 选择器 [class^=box]

    • 选择所有 class 属性值以 box 开头的元素。

    • 示例:

      <div class="box"></div> <!-- 符合 -->
      <div class="box1"></div> <!-- 符合 -->
      <div class="box-dv"></div> <!-- 符合 -->
      
  3. 选择器 [class$=box]

    • 选择所有 class 属性值以 box 结尾的元素。

    • 示例:

      <div class="dv box"></div> <!-- 符合 -->
      <div class="box"></div> <!-- 符合 -->
      <div class="dv-box"></div> <!-- 符合 -->
      
  4. 选择器 [class|=dv]

    • 选择所有 class 属性值等于 dv 或以 dv- 开头的元素。

    • 示例:

      <div class="dv"></div> <!-- 符合 -->
      <div class="dv-box"></div> <!-- 符合 -->
      <div class="dv-box1"></div> <!-- 符合 -->
      
  5. 选择器 [class~=dv]

    • 选择所有 class 属性值包含 dv,且 dv 作为独立的值存在(即 class 是由空格分割的多个值的列表,其中一个值必须是 dv)。

    • 示例:

      <div class="dv box"></div> <!-- 符合 -->
      <div class="box dv"></div> <!-- 符合 -->
      <div class="dv-box"></div> <!-- 不符合 -->
      

后代选择器

后代元素 = 直接后代元素 + 间接后代元素

一般后代表示的就是直接后代元素 + 间接后代元素

而子代表示的就是直接子代元素

所有后代选择器

选择器之间以空格分割

/* 
  .dv元素下 所有有foo class样式的 后代元素
*/
.dv .foo {
  color: red;
}

直接子代选择器

/*
  .dv元素下 所有有foo class样式的 直接后代元素(直接子代元素)
*/
.dv > .foo {
  color: red;
}

兄弟选择器

注意: 在默认情况下,兄弟选择器选中的都是后继兄弟元素

如果需要选中前置兄弟元素,可以结合:not伪元素来进行选择

相邻兄弟选择器

  • 使用符号 + 连接
/*
  有lorem类的元素 后边的第一个兄弟层级的div元素
*/
.lorem + div {
  color: red;
}

全兄弟选择器

  • 使用符号 ~ 连接
/*
  有lorem类的元素 后边的所有的兄弟层级的div元素 (不包括前边的)
*/
.lorem ~ div {
  color: red;
}

选择器组

交集选择器:

交集选择器 --- 需要同时符合两个选择器条件 (两个选择器紧密连接)

LKJDgT.png

/*
  有lorem类的div元素 --- 两者必须同时满足
*/
div.lorem {
  color: red;
}

并集选择器:

并集选择器 --- 符合一个选择器条件即可 (两个选择器以,号分割)

LKJOGE.png

/*
  1. 有lorem类的元素或者div元素 --- 多个条件之间满足其中任意一个即可
  2. 多个条件之间使用逗号进行分割,且推荐每个条件都用新的一行进行表示
*/
.lorem,
div {
  color: red;
}

伪类选择器

Pseudo-classes: 翻译过来是伪类

伪类是选择器的一种,它用于选择处于特定状态的元素 --- 如被点击,被悬浮等

常见伪类分类举例
动态伪类:link、:visited、:hover、:active、:focus
目标伪类:target
语言伪类:lang( )
元素状态伪类:enabled、:disabled、:checked、:selected
结构伪类:nth-child( )、:nth-last-child( )、:nth-of-type( )、:nth-last-of-type( ) :first-child、:last-child、:first-of-type、:last-of-type :root、:only-child、:only-of-type、:empty
否定伪类:not()
其它:placeholder

动态伪类

  • a:link 未访问的链接
  • a:visited 已访问的链接
  • a:hover 鼠标挪动到链接上
  • a:active 激活的链接(鼠标在链接上长按住未松开)
  • :focus当前拥有输入焦点的元素
  1. 除了a元素,:hover, :active也能用在其他元素上

  2. 直接给a元素设置样式,相当于给a元素的所有动态伪类都设置了

    --- 相当于a:link、a:visited、a:hover、a:active、a:focus 都设置了相同的样式

  3. 因为链接a元素可以被键盘的Tab键选中聚焦,所以:focus也适用于a元素

a:link {
  color: red;
}

a:visited {
  color: green;
}

/*
  当a链接被点击了以后
  a链接其实即处于focus状态 也处于active状态
  所以为了确保active状态的样式不被覆盖
  active伪类 推荐 放置到 focus伪类后进行编写
*/
a:focus {
  color: gray;
}

a:hover {
  color: blue;
}

a:active {
  color: orange;
}

/*
  a {
    color: paleturquoise;
  }
*/

注意:

  1. :hover必须放在:link:visited后面才能完全生效
  2. :active必须放在:hover后面才能完全生效
  3. :focus必须放在:hover后, :active之前才能完全生效

所以动态伪类编写顺序推荐为: :link、:visited、:focus、:hover、:active

目标伪类 --- :target

:target 用于匹配那个元素的id属性的值 和 url中的fragment字段的值一致

:target {
  color: red;
}
<div id="foo">foo</div>
<div id="bar">bar</div>
<div id="baz">baz</div>

在本例中, 当URL为http://www.example.com/index.html#bar<div id="bar">bar</div>的颜色会被设置为红色

语言伪类 --- :lang()

  1. lang 属性是一个全局属性,可以在任何 HTML 元素上设置。

    它用于指定元素内容的语言。

    一般设置于html元素上,以便于全局生效。

  2. :lang 伪类选择器用于选择具有特定语言属性的元素。

    它的语法是 :lang(language),其中 language 是一个语言代码。

  3. :lang 伪类选择器中,语言代码不需要加引号。

    因为其本质是语言代码,不是字符串

<div lang="zh-CN">foo</div>

:lang(zh) 选择器会匹配 lang 属性值以 zh 开头的所有元素,包括 zh-CNzh-TW 等。

:lang(zh) {
  color: red;
}

结构伪类

选择器作用
:nth-child(n)css函数调用 n的其值从0开始依次递增 选取当前元素的父元素的第n个子元素
:nth-last-child(n)css函数调用 n的其值从0开始依次递增 从后往前选取当前元素的父元素的第n个子元素
:nth-of-type(n)css函数调用 n的其值从0开始依次递增 选取当前元素的父元素的第n个同类型子元素
:nth-last-of-type(n)css函数调用 n的其值从0开始依次递增 从后往前选取当前元素的父元素的第n个同类型子元素
:first-child等同于:nth-child(1)
:last-child等同于:nth-last-child(1)
:first-of-type等同于:nth-of-type(1)
:last-of-type等同于:nth-last-of-type(1)
:only-child该元素是父元素中唯一的子元素 即匹配没有任何兄弟元素的元素
:only-of-type该元素是父元素中唯一的同类型子元素 即该子元素在父元素中没有其它相同类型的兄弟元素
:root根元素,就是HTML元素
:empty完全空白的元素

:nth-child vs :nth-of-type

<!-- :nth-child(n) -->

<style>
  /* ul下的第三个子元素,且该子元素的类型是li的时候,设置其颜色为红色 */
  /* 
    注意:在JS中 索引是从0开始计算的,但是在css中,索引是从1开始计算的
    也就是说nth-child(3) 选择的是第三个对应的元素
  */
  ul :nth-child(3) {
    color: red;
  }
</style>

<ul>
  <li>content1</li>
  <li>content2</li>
  <!-- content3的颜色被设置成了红色 -->
  <li>content3</li>
  <li>content4</li>
  <li>content5</li>
</ul>
<!-- :nth-last-child(n) -->
<style>
  /* ul下的倒数第二个子元素,且该子元素的类型是li的时候,设置其颜色为红色 */
  ul li:nth-last-child(2) {
    color: red;
  }
</style>

<ul>
  <li>content1</li>
  <li>content2</li>
  <li>content3</li>
  <!-- content4的颜色被设置成了红色 -->
  <li>content4</li>
  <li>content5</li>
</ul>
<!-- :nth-of-type(n) -->
<style>
  /* 
    ul下的第三个子元素,且该子元素的类型是li的时候,设置其颜色为红色
    在计算过程中,不计算其它类型元素
  */
  ul li:nth-of-type(3) {
    color: red;
  }
</style>

<ul>
  <li>content1</li>
  <li>content2</li>
  <span>span 1</span>
  <!-- content3的颜色被设置成了红色 -->
  <li>content3</li>
  <li>content4</li>
  <li>content5</li>
</ul>
<!-- :nth-last-of-type(n) -->
<style>
  /* 
    ul下的倒数第三个子元素,且该子元素的类型是li的时候,设置其颜色为红色
    在计算过程中,不计算其它类型元素
  */
  ul li:nth-last-of-type(3) {
    color: red;
  }
</style>

<ul>
  <li>content1</li>
  <li>content2</li>
  <!-- content3的颜色被设置成了红色 -->
  <li>content3</li>
  <span>span 1</span>
  <li>content4</li>
  <li>content5</li>
</ul>

:nth-child(n)的其它使用方式

:nth-child(n)的其它使用方式同样使用于:nth-last-child(n):nth-of-type(n):nth-last-of-type(n)

/*
  选中所有的偶数列
  :nth-child(2n) 等价于 :nth-child(even)
*/
ul li:nth-child(2n) {
  color: red;
}
/*
  选中所有的偶数列
  :nth-child(2n + 1) 等价于 :nth-child(odd) 等价于 :nth-child(2n - 1)
*/
ul li:nth-child(2n + 1) {
  color: red;
}
/*
  选中第一个子元素
  :nth-child(1) 等价于 :first-child
*/
ul li:nth-child(1) {
  color: red;
}
/*
  -n + X
  选中前X个子元素
*/
ul li:nth-child(-n + 3) {
  color: red;
}
/*
  设置第一个,第五个,第九个,第十三个 ... 子元素的字体颜色为红色
*/
ul li:nth-child(4n + 1) {
  color: red;
}

否定伪类 --- :not()

:not(x) --- x是一个简单选择器, 可以是元素选择器、通用选择器、属性选择器、类选择器、id选择器、伪类(除否定伪类)等任何合法的选择器

在设置:not(x)的时候,一般会添加一个限制条件, 例如xxxx :not(x), 从而避免将样式添加到bodyhtml等元素上

/* .dv元素下 没有.lorem 这样一个类的元素 */
.dv :not(.lorem){
  color: red;
}

:is()

:is 选择器用于减少冗长的选择器列表。它接受一个选择器列表,并匹配其中的任何一个选择器

:is(.class1, .class2, .class3) > p {
  color: red;
}

等价于

.class1 > p,
.class2 > p,
.class3 > p {
  color: red;
}

:is 选择器的特异性由其包含的选择器中特异性最高的那个决定

:is(#id, .class, article) {
  margin: 20px;
}
  • #id 的特异性是 0100
  • .class 的特异性是 0010
  • article 的特异性是 0001

在这种情况下,:is(#id, .class, article) 的特异性将是 0100,因为 #id 的特异性最高。

:where()

:where 选择器的功能与 :is 类似,但它具有一个重要的区别::where 选择器的特异性(specificity,也就是选择器的优先级)始终为零。这意味着它不会影响选择器的优先级。

article {
  margin: 10px;
}

:where(article, section, aside) {
  margin: 20px;
}

因为:where中的选择器优先级为0,所以article元素的边框值是10px

/* article 的特异性是 0001 */
article {
  margin: 10px;
}

/* :is(article, section, aside) 的特异性是 0001 */
:is(article, section, aside) {
  margin: 20px;
}

最终,article元素的边框值是20px

:has()

A:has(B) 选择的是那些包含至少一个 B 元素的 A 元素。然后,你可以对这些 A 元素应用相应的样式

:has() 是一个相对较新的 CSS 选择器, 浏览器支持情况可能不太理想

<!-- .container背景会变黄 -->
<div class="container">
  <p>Paragraph 1</p>
  <span>Span 1</span>
</div>

<!-- .container背景不会变黄 -->
<div class="container">
  <p>Paragraph 2</p>
</div>

<style>
.container:has(span) {
  background-color: yellow;
}
</style>
/* 选择包含 <p>、<span> 或 <h3> 元素中的任意一个的 .box 元素 */
.box:has(p, span, h3) { 
  display: none;
}
<style>
  /*
    找到div元素,且该元素后边的直接兄弟元素有.lorem
    所以其本质就是找有.lorem类的前一个div元素
  */
  div:has(+ .lorem) {
    color: red;
  }
</style>

<div>lorem</div>
<div class="lorem">lorem</div>

伪元素

常用的伪元素有

  • :first-line、::first-line
  • :first-letter、::first-letter
  • :before、::before
  • :after、::after
  • :: -webkit-scrollbar
  1. 为了区分伪元素和伪类,建议伪元素使用2个冒号,比如::first-line

  2. 伪元素用于选择某一个具体的元素中某一个或某些具体的部分

  3. 行内替换元素一般不能设置伪元素,因为对其设置伪元素其实本质

    是给其占位元素进行设置,最终会被实际需要渲染的元素给替换掉

::first-line,::first-letter

::first-line可以针对首行文本设置属性

::first-letter可以针对首字母设置属性

/* .lorem的第一行文本的字体颜色设置为红色 */
.lorem::first-line {
  color: red;
}

/* .lorem的第一行文本中第一个字的字体颜色设置为红色 */
.lorem::first-letter {
  color: red;
}

::before::after

::before::after用来在一个元素的内容之前或之后插入其他内容(可以是文字、图片)

::before::after常通过 content 属性来为一个元素添加修饰性的内容

往一段文本的前后加入对应的内容的时候,我们可以在元素的前后插入对应的内容

<div>
  <span>before</span>
  Lorem ipsum dolor sit amet consectetur adipisicing elit.
  <span>after</span>
</div>

这样做存在如下问题:

  1. 如果多处文本前后需要添加相同的内容的时候,这么做必须需要重复编写大量相同的代码
  2. 因为文本内容和span元素之间有换行,所以在前后插入的元素和文本之间必然存在一个空格

LKEPlw.png

此时,CSS就为我们提供了::before::after伪元素来实现在一个元素的前边和后边插入对应的图片或文本

基本使用

  1. 插入文本
/* 在.lorem后边添加上foo文本 */
.lorem::after {
  /* 设置的内容 */
  content: 'foo';

  /* 对插入的内容设置对应的样式 */
  color: red;
  font-size: 30px;
}
  1. 插入图片
/* 在.lorem后边插入图片 */
.lorem::after {
  /*
    1. 可以使用url函数来设置插入的图片的路径
    2. url函数的参数可以使用引号进行包裹
    3. 在css中的引号 推荐使用 双引号 而不是 单引号
  */
  content: url("./images/avatar.jpg");

  color: red;
  font-size: 30px;
}
  1. 插入自定义图形
/* 在.lorem后边插入一个 50 * 50的红色矩形 */
.lorem::after {
  /*
    对于伪类元素 content属性是不可以省略的
    即使不需要设置插入的内容 --- 此时可以使用空字符串进行代替
  */
  content: "";

  /*
    默认情况下,::before 和 ::after 插入的元素
    都是行内非替换元素 所以需要将他们转换为行内块元素
    因为 行内级元素 是无法设置对应的width和height的
  */
  display: inline-block;
  background-color: red;
  width: 50px;
  height: 50px;
}

:: -webkit-scrollbar

可以通过::-webkit-scrollbar来控制滚动条的样式,一般用于清除默认的滚动条

.lyrics::-webkit-scrollbar {
  display: none;
}