【前端】详解11种CSS选择器

正如在博客《前端三要素之JavaScript》所说,年假期间基本刷完了JavaScript与CSS,最近正好有时间全部转化为博客。


以下代码均本人手敲,可放心食用。


另外,十分感谢Pink老师的课程,详细全面又细节!!

CSS的选择器简介

什么是选择器?

当浏览器拿到一个页面的时候,会从以下三个角度去看这个页面:

  • 基础框架(DOM元素):也就是有各个HTML标签
  • CSS样式:一个不带样式的纯HTML文档就像是一个被拔了毛的孔雀,看起来丑丑的像是正待下锅的老母鸡,而CSS可以让页面更加的漂亮美观
  • JavsScript代码:JavaScript主要用来控制页面的逻辑,如点了一个按钮,输入了一行内容等

选中我们想要修改样式的标签,并对其定义样式的“媒介”,就是我们说的选择器。

在行内式与外联式中我们这样使用选择器:

选择器 {
  /* 元素样式; */
}

选择器分类

CSS有很多的选择器,按照选择器类型可以分为基础选择器复合选择器

在CSS2之前有一些选择器,我们称为传统选择器

CSS3种出现的选择器,我们称为新增选择器

选择器的使用

CSS样式的使用又分为:

  • 行内式
  • 嵌入式
  • 外联式
  • 行内式:是指写在元素内的style=""属性中的

  • 嵌入式:是指写在整个页面的<style>标签中的(一般放在head标签内)

  • 外联式:是指在文件外部定义一个.css文件,并通过link标签将样式引入进来。

要注意:行内式不存在选择器,只有嵌入式与外联式才会存在选择器。

为了能够能好的继续阅读博客,这里对这三种使用方式进行举例,内容很简单:我们让一个div的背景变为绿色。

行内式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>选择器的三种使用方式</title>
</head>
<body>
  <!-- 行内式:直接在被作用的元素内通过style属性进行定义并使用 -->
	<div style="background-color: green">我是Jim.kk</div>
</body>
</html>

嵌入式

以下代码中使用了一个简单的标签选择器,后面会讲到,这里只需要知道style标签中的内容会作用到下面的div标签上即可。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>选择器的三种使用方式</title>
    <style>
      	/* 嵌入式:写在head中的style标签中 */
        div {
            background-color: green;
        }
    </style>
</head>
<body>
  <!-- 被作用的元素 -->
	<div>我是Jim.kk</div>
</body>
</html>

外联式

我在html文件的位置创建一个css文件夹,里面放一个a.css文件,文件结构如下:

在这里插入图片描述

css文件中做如下定义:

以下代码中使用了一个简单的标签选择器,后面会讲到,这里只需要知道style标签中的内容会作用到div标签上即可。

div {
    background-color: green;
}

我们在HTML文件的头部中通过link标签将该文件引入,以下为固定写法:

<link rel="stylesheet" href="css文件路径">

HTML文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>选择器的三种使用方式</title>
  	<!-- 外联式固定写法,请勿随意修改 -->
    <link rel="stylesheet" href="css/a.css">
</head>
<body>
<div>我是Jim.kk</div>
</body>
</html>

以上代码在浏览器中的表现如下:

在这里插入图片描述

CSS三大特性

CSS样式又有层叠性、继承性、优先级。这里不多赘述,后面写好博客之后我会在这边放相关的博客链接,这里仅对层叠性和继承性做简要介绍。

层叠性:若是在不同选择器中定义了相同的样式,则根据"就近原则":靠近元素的样式会生效,这里行内式 > 嵌入式与外联式,且嵌入式与外联式中,写在下面的样式会覆盖上面的样式。

继承性:父级的一些属性可以继承给子类,如一个div定义了字体颜色是白色,那么若是不对其内部的标签做特殊定义,其内部标签的文字颜色则都会是白色。

优先级:这个比较复杂,且下文用不到,暂不赘述,后面等我补充博客(挖坑)

以上就是对选择器的介绍,我们要知道选择器在什么时候使用以及CSS的三种使用方式。下面将根据传统选择器与新增选择器进行分类,根据基础选择器与复合选择器为子分类,描述选择器的各种类型。

以下代码本人均手敲且验证,请放心食用。

传统选择器

在对选择器的介绍中,我都会采用嵌入式的书写方式,比较好展现。下面请开始品尝美味的“芝士”吧。

基础选择器

  1. 基础选择器包含:标签选择器、ID选择器、类选择器、多类选择器。其中ID只能作用在一个元素上,其余选择器可以作用在多个元素上
  2. ID选择器建议定义结构,其余选择器建议用来定义样式
  3. 多个选择器可以在遵循CSS三大特性的基础上复合使用

标签选择器

就如同上面的示例中的代码一样,选择器的名称为一个标签名称,该选择器会作用在页面中的每一个标签上。这种选择器就是标签选择器。

标签选择器是一个范围选择器,一次可以作用在多个元素上。

标签选择器的基础语法如下:

标签名称 {
  样式;
}

以下我定义了三个div与三个p标签(忽略),定义两个css样式(如下):

div {
    height: 30px;
    background-color: #8d8dff;
    margin: 10px 0;
}
p {
    background-color: #c2ffc2;
}

则这六个块元素在浏览器中的表现如下:

在这里插入图片描述

以上便是标签选择器,可以作用在每一个符合规范的“标签”元素上。

类选择器

类选择器也是一个复合选择器,与标签选择器不同的是,它将不会作用在每一个标签,而是作用在我们定义的类名上,我们可以在多个需要生效的标签内定义同一个类名,然后通过类选择器同时对这几个元素生效。

类选择器的语法如下:

.类名 {
  样式;
}

以下我定义三个div,让第一个div和第三个div背景为紫色,第二个div颜色不变,代码如下:

<head>
    <meta charset="UTF-8">
    <title>标签选择器</title>
    <style>
        .box {
            background-color: #8d8dff;
        }
    </style>
</head>
<body>
    <div class="box">我是Jim.kk</div>
    <div>我是Jim.kk</div>
    <div class="box">我是Jim.kk</div>
</body>

可以看到第一个和第三个盒子的类名都是box,而第二个盒子没有类名,不符合我们定义的类选择器的规则,所以这里只有第一个盒子和第三个盒子会被选中,第二个盒子没有样式。

以上代码在浏览器中的表现如下:

在这里插入图片描述

可以看到确实只有第一个盒子和第三个盒子的样式生效了,第二个盒子没有任何样式。

类选择器2 | 多类名

多类名可以帮我们避免掉一些重复的代码,降低代码体量的同时增加代码的可阅读性

多类名是指在标签中多类名,不是指在定义选择器的时候定义多个类名选择器

我们定义元素的时候可以取一个或多个类名,在一些情况下,多个元素的样式**“大差不差”**,比如我们存在三个div元素,它们的宽高背景颜色等都相同,只有文字颜色不一样,如果我们像下面这样写代码,那是及其浪费代码空间的:

请注意:这里是错误的示例

.box1 {
    /* 以下样式为重复样式 */
    height: 30px;
    width: 200px;
    background-color: #8d8dff;
    margin: 10px 0;
    /* 以下样式为特殊样式 */
    color: pink;
}
.box2 {
    /* 以下样式为重复样式 */
    height: 30px;
    width: 200px;
    background-color: #8d8dff;
    margin: 10px 0;
    /* 以下样式为特殊样式 */
    color: red;
}
.box3 {
    /* 以下样式为重复样式 */
    height: 30px;
    width: 200px;
    background-color: #8d8dff;
    margin: 10px 0;
    /* 以下样式为特殊样式 */
    color: #fff;
}

以上代码是可以生效的,是完全没有问题的,但是我们多次对不同的盒子进行了相同的描述,大大增加了代码量、降低了代码的可阅读性,有没有办法可以降低代码的书写量呢?当然可以:我们可以对这三个盒子定义多个类名,比如他们都是一个box,则我们可以将重复的代码写在#box中,而对于字体颜色我们做一个特例。

代码如下:

<head>
    <meta charset="UTF-8">
    <title>标签选择器</title>
    <style>
        .box {
            /* 以下样式为重复样式 */
            height: 30px;
            width: 200px;
            background-color: #8d8dff;
            margin: 10px 0;
        }
        .pinkfont {
            color: pink;
        }
        .redfont {
            color: red;
        }
        .whitefont {
            color: #fff;
        }
    </style>
</head>
<body>
    <div class="box pinkfont">我是Jim.kk</div>
    <div class="box redfont">我是Jim.kk</div>
    <div class="box whitefont">我是Jim.kk</div>
</body>

以上代码中,我们对每一个div都定一个两个类名,其中一个是box用来指定整个div的样式,另一个类名则每个都不一样,用来指定文字的样式。这样的话我们就可以避免多次书写重复代码,但是上面两段代码的样式表现是一样的。

以上两段代码在浏览器中的表现均如下:

在这里插入图片描述

ID选择器

ID选择器顾名思义就是根据元素的ID选择一个元素。与上面所有选择器都不太同的是,ID选择器一次只能选择一个元素(因为HTML不同元素不能使用同一个ID)。

工作中推荐样式使用类定义,结构使用ID定义

ID选择器的基础语法如下:

#元素ID {
  样式;
}

注意:ID选择器以#开头,类选择器以.开头。

以下我定义三个盒子,它们的ID分别是box1~box3,分别使用ID选择器来定义不同的样式,代码如下:

<head>
    <meta charset="UTF-8">
    <title>标签选择器</title>
    <style>
      	/* 为每个ID定义一个样式 */
        #box1 {
            background-color: #8d8dff;
            color: #fff;
            margin: 10px;
        }
        #box2 {
            background-color: #5e5eff;
            color: #d3d3d3;
            margin: 10px;
        }
        #box3 {
            background-color: #2424ff;
            color: #959595;
            margin: 10px;
        }

    </style>
</head>
<body>
  	<!-- 为每个DIV定义一个ID -->
    <div id="box1">我是Jim.kk</div>
    <div id="box2">我是Jim.kk</div>
    <div id="box3">我是Jim.kk</div>
</body>

以上代码在浏览器中的表现如下:

在这里插入图片描述

通配符选择器(全局选择器)

由于有的HTML标签会自带一些原生样式(比如无序列表ul+li会自带前面的小黑点,body会有padding等),我们需要初始化这个页面中所有的元素样式,将这些自带的样式全部消除掉,这时候就可以使用我们的通配符选择器。

通配符选择器的基本书写样式如下:

* {
  样式;
}

比如我们要屏蔽掉所有的padding和margin,我们就可以像下面一样写:

* {
  padding: 0;
  margin: 0;
}

复合选择器

以上的选择器都是单一单词组成的选择器,通配符选择器一般是由多个单词组成的选择器,下面请看示例:

后代选择器

后代选择器是一种非常常见的选择器,可以控制父元素内所有子元素(可以是某一个或者某一类或者其它)的样式,这是及其方便的,比如我们页面中有100个input标签,我想要改变10个外边框为红色,5个没有边框,其余不变,这时候就可以使用后代选择器。

后代选择器的标准写法:

父元素 后代元素 {
    后代元素样式;
}

由于生效的不仅仅是子元素,还有子元素的子元素与子元素的子元素的子元素…所以这里说是“后代”,而不是“子”。

(为了说的方便,后面还是以父子相称)

下面举个例子:

我们写10个input输入框,其中前3个的父元素是一个id为box1的div,这三个的输入框是红色,最后2个输入框被一个id为box2的父元素包围,它们两个的外边框为紫色,背景色是粉色,且最后一个input还被一层input包裹

HTML代码如下:

<body>
<div id="box1">
    <!-- 下面三个是box1的子元素 -->
    <input type="text">
    <input type="text">
    <input type="text">
</div>
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<div id="box2">
    <!-- 下面的input和div是box2的子元素-->
    <input type="text">
    <div>
        <!-- 下面的input是box2的孙子元素咯 -->
        <input type="text">
    </div>
</div>
</body>

给这段代码以css如下:

#box1 input {
    border: 1px solid red;
}
#box2 input {
    border: 1px solid #8d8dff;
    background-color: pink;
}

以上代码在浏览器中的表现如下:

0在这里插入图片描述

可以看到,通过这种方式,我们不需要一个一个定义class然后去书写该class的样式,或者是多个ID对应的多个样式,而是只需要一个父元素包裹,就可以更改该父元素下面的所有样式了,让“范围”变得更加灵活了。

工作中这种样式在“表单提交”之类的代码中很常见。

再次注意:后代选择器不是对“子元素”生效,而是对“后代”都生效,这点要与“子元素选择器”区分开哦。

子元素选择器

奇了怪了?好像上面的“后代选择器”就已经能够很方便的修改某个父元素下的所有样式了,这里怎么还会出现一个子元素选择器呢??

答案就在“后代选择器”的最后一句话中。

试想一下:如果我们想要修改某个元素其子元素都为某种状态,但是孙子元素保持不变,这时候就不可以使用后代选择器了。

为了实现这种场景,CSS为我们提供了子元素选择器:子元素选择器仅对孩子生效,对孙子不生效

子元素选择器的标准语法如下:

父元素>子元素 {
    子元素样式;
}

我们使用“后代选择器”中相同的HTML结构,将CSS样式修改为子元素原则器试一下,(为了防止有小伙伴直奔子元素选择器而来却找不到HTML代码,这里也贴一下)HTML代码如下:

<body>
    <div id="box1">
        <!-- 下面三个是box1的子元素 -->
        <input type="text">
        <input type="text">
        <input type="text">
    </div>
    <input type="text">
    <input type="text">
    <input type="text">
    <input type="text">
    <input type="text">
    <div id="box2">
        <!-- 下面的input和div是box2的子元素-->
        <input type="text">
        <div>
            <!-- 下面的input是box2的孙子元素咯 -->
            <input type="text">
        </div>
    </div>
</body>

CSS样式如下:

#box1>input {
    border: 1px solid red;
}
#box2>input {
    border: 1px solid #8d8dff;
    background-color: pink;
}

以上代码在浏览器中的表现如下:

在这里插入图片描述

可以看到正如我们描述的一样,box1和box2的亲儿子都生效了,但是孙子却没有生效。

并集选择器

有的时候我们可能会想将相同的样式作用在几个或者几类毫无关联的元素身上,这时候就需要用到并集选择器。

并集选择器有以下特点:

  1. A∪B,也就是AB都会生效
  2. 代码中集合与集合之间用逗号隔开且可以无限增加
  3. 并集选择器中的每一个集合既可以是一个基础选择器,也可以是一个复合选择器

并集选择器的标准写法:

A,
B {
    /* A和B都会生效的样式 */
}

下面举个简单的例子:我元素中我有一个输入框和一个DIV盒子(盒子宽高均为100px),我让他们的背景、边框、等内容都保持一致。

HTML结构代码如下:

<body>
    <input type="text">
    <div style="width: 100px;height: 100px">我是Jim.kk</div>
</body>

CSS代码如下:

div,
input {
    border: 2px solid #8d8dff;
    background-color: pink;
}

以上代码在浏览器中的表现如下:

在这里插入图片描述

可见两个元素确实是拥有了相同的样式。

如果没有并集选择器的话,我们的代码只能是像下面一样写:

div {
    border: 2px solid #8d8dff;
    background-color: pink;
}


input {
    border: 2px solid #8d8dff;
    background-color: pink;
}

有了并集选择器,我们直接节省了一半的代码量,所以并集选择器的功能其实就是给两个样式一样的元素合并起来。

伪类选择器

伪类选择器是一种比较有意思的选择器,它可以定义一些鼠标点击或移上去、输入框获取焦点时的样式

(有点像是JS中的鼠标移入移除或over等,只不过这里是写在css中的,更加方便)。

伪类选择器的书写样式如下:

元素:触发条件 {
    /* 样式 */
}
触发条件

伪类选择器的触发条件可以是多种多样的,这里简单介绍三种:

  1. 通用型
属性说明
E:link选择所有未被访问的链接
E:hover选择鼠标指针位于其上的链接
E:active选择活动链接(鼠标按下未弹起的链接)
  1. <a>标签链接类
属性说明
a:visited选择所有已被访问的连接
  1. <input>输入框
属性说明
input:focus当该输入框获取了焦点时候的选择器
示例1 | 小盒子变色 :hover的使用

一下举个简单的例子:当鼠标移动到宽高为200的小盒子上时,小盒子改变颜色。

HTML结构代码如下:

<body>
    <div style="width: 200px;height: 200px">我是Jim.kk</div>
</body>

CSS 样式代码如下:

div {
    background-color: pink;
}
div:hover {
    background-color: #8d8dff;
}

以上代码在浏览器中的表现如下:

在这里插入图片描述

示例2 | a链接变色 :hover:visited的使用

html中的a标签默认是蓝色,点击之后颜色变深代表已经访问过(鼠标放上去应该也有一个状态,不过我的浏览器怎么没反应),若是我想让a标签更改一个颜色,默认是灰色,鼠标放上去变成红色,访问过的标签是绿色,则可以像下面一样定义CSS:

HTML代码就省略了,就一个简单的a标签

a {
    color: gray;
}
a:hover {
    color: red;
}
a:visited {
    color: green;
}

在这里插入图片描述

效果如我们所想。

示例3 | 输入框获取焦点后变色 :focus的使用

HTML的输入框有几个默认的样式,比如一个黑色的外边框border,获取焦点后会有一个蓝色或黑色的外框outline

如下所示:

在这里插入图片描述

我们通过定义input:focus来控制获取焦点时候的样式,比如我需要一个紫色的外边框(border),再来一个阴影吧,看起来效果明显一些,并且通过outline: none来消除掉原本的外边框(outline)。

代码如下所示:

<body>
<div>
    输入框1:
    <input type="text">
</div>
<div>
    输入框2:
    <input type="text">
</div>
</body>

CSS代码如下:

input:focus {
    outline: none;
    border:  #8d8dff 1px solid;
    box-shadow: 0 0 3px gray;
}

以上代码在浏览器中的表现如下:

在这里插入图片描述

CSS3 新增选择器

属性选择器

当我们给元素添加样式的时候,可能会出现我们要添加样式的多个元素都具有某个属性,比如id或者class,这时候我们就可以考虑采用属性选择器。

另外,实际开发中我们可能会常用Emmet语法,比如#box$*5+Tab键代表生成5个div,它们的ID分别是box1~box5,这时候我们也可以使用属性选择器,单独去选中这五个盒子,只需要div[id^=box]即可(代表有id属性且值以box开头)

基础语法

选择符简介
E[att]选择具有att属性的E元素
E[att="val"]选择具有att且属性值等于val的E元素
E[att^="val"]选择具有att属性且值以val开头的E元素
E[att$="val"]选择具有att属性且值以val结尾的E元素
E[att*="val"]选择具有att属性且值中含有val的E元素

表格中E代表元素,att代表属性。

简单示例

下面我定义一个HTML结构,然后解释上面表格中的作用形式。

<div id="box">我是box</div>

<div id="box1">我是box1</div>
<div id="box2">我是box2</div>
<div id="box3">我是box3</div>

<div id="1box">我是1box</div>
<div id="2box">我是2box</div>
<div id="3box">我是3box</div>

<div id="div1">我是Div1</div>
<div class="div2">我是class div2</div>

下面定义5个CSS,看他们的作用范围:

  1. 不看属性值
div[id] {
    /* 生效范围:作用于除了'class=div2'以外的所有元素; */
}

解释说明:该选择器意思是所有包含id的div,所以除了最后一个div不包含id,不生效,其余均包含ID,所以都生效。

  1. 精准匹配属性值
div[id="box"] {
    /* 生效范围:第一个div; */
}

解释说明:该选择器意思是包含id且值是’box’的div,很明显只有第一个div匹配。

  1. 值以xxx开头的属性
div[id^="box"] {
    /* 生效范围:前四个div; */
}

解释说明:该选择器意思是包含id且值是’box’!开头!的div,box是以box开头的,另外box1、2、3也是以box开头的。

  1. 值以xxx结尾的属性
div[id$="box"] {
    /* 生效范围:第一个和第567个div */
}

解释说明:该选择器意思是包含id且值是’box’!结尾!的div,box是以box结尾的,另外box1、2、3也是以box结尾的。

  1. 属性含有带xxx的值
div[id*="box"] {
    /* 生效范围:除了最后两个div以外全部都生效; */
}

解释说明:该选择器意思是包含id且值!包含!‘box’的div,box是包含div的,另外box1/2/3以及1/2/3box也是包含’box’的,而倒数第二个div的id是’div1’,其中并不包含box这个单词,所以不生效,最后一个div没有id,也不生效。

结构伪类选择器

我们之前学过“伪类选择器”,主要内容为元素与人的交互效果。这里又有一种“结构伪类”选择器,主要作用是从父元素下面选择子元素,要记得区分。

结构伪类选择器的书写方法像是伪类选择器,但是使用效果却像是子元素选择器或后代选择器,只不过比子元素选择器或后代选择器更加的灵活。

选择符简介是否仅对某类元素生效
E :first-child匹配父元素中的第一个子元素E×
E :last-child匹配父元素中最后一个子元素E×
E :nth-child(n)匹配父元素中的第n个子元素E(n可以是数字、关键字、或公式)
数字就是匹配第几个(从1开始)
关键字:even是偶数(匹配2、4、6…),关键字odd是奇数,匹配1\3\5…
×
E :first-of-type按类型指定第一个E
E :last-of-type按类型指定最后一个E
E :nth-of-tyoe(n)指定类型E的第n个

注意有个空格

按照生效方式,他们可以分为两种类型(child结尾一类,of-child结尾一类):

类型一类型二
E :first-childE :first-of-type
E :last-childE :last-of-type
E :nth-child(n)E :nth-of-tyoe(n)

Child类型(非Type类型)

示例1.1 | 某个子元素变色

为了能一次性呈现表一中1/2/3三个选择器的效果,我们这里直接定义一个ul>li,代码如下:

<head>
    <meta charset="UTF-8">
    <title>新增选择器</title>
    <style>
        ul :first-child {
            color: red;
        }
        ul :nth-child(3) {
            color: green;
        }
        ul :last-child {
            color: blue;
        }
    </style>
</head>
<body>
<ul>
    <li>我是红色的Jim.kk</li>
    <li>我是Jim.kk</li>
    <li>我是绿色的Jim.kk</li>
    <li>我是Jim.kk</li>
    <li>我是Jim.kk</li>
    <li>我是Jim.kk</li>
    <li>我是Jim.kk</li>
    <li>我是蓝色的Jim.kk</li>
</ul>
</body>

代码说明:以上代码有三个选择呢其,他们父元素都是ul,所以生效的地方都是ul的子元素,以上代码的效果分别如下:

  • 选择器1:规定ul的第一个(:first-child)子元素是红色
  • 选择器2:规定ul的第三个(:nth-child(3))子元素是绿色
  • 选择器3:规定ul的最后一个(:last-child)子元素是蓝色

将以上代码放到HTML网页中,效果如下:

在这里插入图片描述

可以看到效果确实如我们所想。

示例1.2 | 思考:如果总共只有三个元素呢?

写博客的时候突然想到这个小问题,如果只有三个元素,那么第三个元素(同时又是最后一个元素)字体会是什么颜色呢?

猜一下,是红色还是绿色还是蓝色还是黑色呢?

其实很简单:是蓝色。

原因:当只有三个元素的时候,第二个选择器跟第三个选择器的效果重合了,根据三大原则中的层叠性(就近原则,最下面的生效),所以第三个选择器的效果会覆盖第二个选择器。

看在浏览器中的效果如下:

在这里插入图片描述

可以看到,本来是“绿色”的Jim.kk(第三个),现在成了蓝色(最后一个)。

示例2 | :nth-child(关键字) | 斑马纹的列表
<head>
    <meta charset="UTF-8">
    <title>新增选择器</title>
    <style>
        * {
            /* 加上这一行屏蔽掉list的原生样式 */
            list-style: none;
        }
        ul :nth-child(odd) {
            background-color: #ececec;;
        }
    </style>
</head>
<body>
<ul>
    <li>我是Jim.kk</li>
    <li>我是Jim.kk</li>
    <li>我是Jim.kk</li>
    <!-- 此处省略很多行 -->
    <li>我是Jim.kk</li>
</ul>
</body>

以上选择器中:nth-child规定为关键字odd,代表奇数行生效,所以以上代码只有奇数行的背景颜色会变为浅灰色,其余颜色不变,所以会呈现出斑马纹效果。

以上代码在浏览器中的效果如下所示:

在这里插入图片描述

如果将odd修改为even,则会由奇数行生效变为偶数行生效,所以原本是1、3、5、7、9行颜色变灰,改为even之后,是2、4、6、8行变灰。这个自己尝试吧!

示例3 | :nth-child(公式) | 灵活运用

如果要在:nth-child()中添加公式,则公式有且只有一个变量n,n表示从第0个(第0个并不存在,后面会解释)直到最后一个(也就是全部),全部都生效。

公式具有以下几种简单的写法,在此仅做示例:

公式说明
n全部生效
2n仅生效偶数个(相当于关键字even)
2n+1/2n-1仅生效奇数个(相当于odd)
n+m(m是一个整数)从第m个开始生效
-n+m(m是一个整数)从第0个到第m个生效

前面为什么说是从"并不存在"的第0个开始生效呢?如果是从第1个开始生效的话,那么2n表示偶数个很好理解,2n-1表示奇数个也很好理解,但是2n+1则表示"从第三个开始的奇数个",这跟我们观察的效果是不一样的。

另外,如果是n+m的情况,0+m=0,1+m=m+1,如果n表示从第一个开始,m取值为5的话,实际会从第六个开始生效,这也是十分不方便的。

接下来看一下他们的生效效果吧。

以下代码都是一个ul里面包含很多很多个li,HTML代码不提供,css代码如下,仅需修改小括号里的内容即可)

* {
    list-style: none;
}
ul :nth-child(n) {
    background-color: #ececec;;
}
  1. n | 全部生效

效果如下:

在这里插入图片描述

  1. 2n | 偶数生效

在这里插入图片描述

  1. 2n+1/2n-1 | 奇数生效

在这里插入图片描述

  1. n+m | 从第m个开始生效

n+5示例

在这里插入图片描述

  1. -n+m | 0~m个生效

-n+5示例

在这里插入图片描述

可以看到是0~5个有背景颜色

Type类型

上面介绍了以-child结尾的结构伪类选择器,接下来看一下以-type结尾的结构伪类选择器。

通过一个问题进入到-type类型的讲解:如果我一个div中有随机个p标签和span标签,我想让第三个p标签(忽略span标签,只看第三个p标签),通过上面的结构伪类选择器可以实现吗?

似乎不太行?换种角度思考这个问题,我们能不能通过后代选择器(或子元素选择器)+结构伪类选择器来实现这个需求呢?下面简单尝试一下。

尝试1 | 后代选择器+-child结构伪类选择器

为了节约代码行数和博文长度,这里我们让第二个p标签变色

<head>
    <meta charset="UTF-8">
    <title>新增选择器 | 结构伪类选择器+子元素选择器</title>
    <style>
        div p:nth-child(2) {
            color: red;
        }
    </style>
</head>
<body>
<div>
    <span>我是span1</span>
    <p>我是p1</p>
    <span>我是span2</span>
    <p>我是p2,我想要红红火火</p>
    <span>我是span3</span>
    <p>我是p3</p>
</div>
</body>
</html>

猜测以上的效果?p2会“红红火火”吗?请看下图:






在这里插入图片描述

注意:可以看到,按照题目中要求的“第二个p标签”并没有变化,变化的是第二个标签(虽然它也是p标签),也就是第一个p标签。这时候怎么办呢?

答案很简单,我们使用-type类型的结构伪类选择器就可以,其余不变,对CSS做如下修改:

div p:nth-of-type(2) {
    color: red;
}

以上代码在浏览器中的效果如下:

在这里插入图片描述

可以看到,现在我们已经可以实现某个某类的p标签变色。

两种结构伪类选择器对比

两种结构伪类选择器在用法上(我是指写法)是比较相似的,十分好理解,两者只有以下不同:

  1. -child若是配合子元素选择器使用,它会先去查找-child指定的那个子元素,若是该元素是指定的子元素类型则生效,否则不生效
  2. -type若是配合子元素选择器使用,它会先将父类下的该种子元素全部做个排序,随后根据下标找到结构伪类选择器指定的子元素并生效

复现一下1中提到的情况:若找到的子元素不是我们指定的子元素类型则不会生效

<head>
    <meta charset="UTF-8">
    <title>新增选择器 | 结构伪类选择器+子元素选择器</title>
    <style>
        div p:nth-child(3) {
            color: red;
        }
    </style>
</head>
<body>
<div>
    <span>我是span1</span>
    <p>我是p1</p>
    <span>我是span2</span>
    <p>我是p2</p>
    <span>我是span3</span>
    <p>我是p3</p>
</div>

以上代码中,我们用后代选择器指定生效对象必须是p标签,但是却是使用的-child结构伪类选择器,它的效果如下:

在这里插入图片描述

可以看到没有任何效果,这是因为该选择器会先寻找第三个元素,这时候发现它不是p,所以不生效。

伪元素选择器

在一些情况下(比如使用隔墙法或双伪元素发清除浮动,又或者使用矩形+三角形做出梯形效果)我们需要在盒子的头部或尾部添加一个盒子模型,通常这个盒子模型没有什么用,也没有内容,只是放在那里达成效果,这时候如果我们通过HTML代码来完成的话(注意一个页面中可能会多次出现这种场景),难免会让HTML结构变得臃肿不堪,不便于阅读,这个时候我们就可以考虑采用伪元素选择器,在CSS中给某个元素添加一个子元素

伪元素选择器就是利用CSS来创建(伪)HTML标签

选择符简介
::before在元素内部的前面插入内容
::after在元素内部的后面插入内容
  1. beforeafter都是创建一个元素,但是属于行内元素
  2. 新创建的这个元素在文档书中是找不到的,所以称为伪元素
  3. 语法:element::before{}
  4. beforeafter必须有content属性
  5. before在父元素内容的前面创建元素,after在父元素内容的后面插入元素
  6. 伪元素选择器和标签选择器一样,权重为1(这一点本博客没有介绍,可以自己去查资料)

伪元素选择器在浏览器中的显示效果如下:

在这里插入图片描述

基本语法

div::before {
    /* 这一行是必填项 */
    content: '盒子里显示的内容';
}

div::after{
    /* 这一行是必填项 */
    content: '盒子里显示的内容';
}

示例1 | 在盒子内部两侧各加一个伪元素选择器

<head>
    <meta charset="UTF-8">
    <title>伪元素选择器</title>
    <style>
        div {
            background-color: pink;
            /*text-align: center;*/
        }
        span {
            background-color: #8d8dff;
            display: inline-block;
            margin: 0 10px;
        }
        /* 插入Before伪元素 */
        div::before {
            content: '我是Before';
            background-color: lightgreen;
        }
        /* 插入After伪元素 */
        div::after {
            content: '我是After';
            background-color: #c2ffc2;
        }
    </style>
</head>
<body>
<div>
    <span>我是Jim.kk</span>
    <span>我是Jim.kk</span>
    <span>我是Jim.kk</span>
</div>
</body>

以上代码在浏览器中的表现如下:

在这里插入图片描述

可以看到,HTML结构代码中div只有三个子元素,但是实际显示的却是5个子元素,这是因为我们在该元素内部添加了两个伪元素。

示例2 | 通过伪元素选择器实现一个带箭头的梯形(气泡)

先过渡一下:我们在CSS中除了矩形基本就是圆角矩形或圆形,很少会见到三角形,下面我们用一段代码简单看看如何实现一个三角形。

定义三角形的步骤:

  1. 定义一个宽度和高度为0的盒子
  2. 设置border的宽度为x
  3. 设置border的颜色

请看以下代码:

div {
  width: 0;
  height: 0;
  border-left: 20px solid black;
  border-bottom: 20px solid green;
  border-right: 20px solid blue;
  border-top: 20px solid pink;
}

我们对一个div做如上定义之后,该div在浏览器中的显示效果如下:

在这里插入图片描述

将三条边设置为透明,则可以达到下面这种效果:

div {
    width: 0;
    height: 0;
    border: 20px solid transparent;
    border-right: 20px solid pink;
}

以上代码利用了三大特性的层叠性

以上代码在浏览器中的显示效果如下:

在这里插入图片描述

这样我们就实现了一个向左的箭头。

如果我们通过伪类选择器,在一个紫色的盒子中的before位置实现这样的一个三角形,并通过定位让三角形向左移动一定距离,就可以实现一个气泡。

CSS代码如下:

div {
    background-color: #8d8dff;
    width: 200px;
    height: 100px;
    /* 父相子绝:父亲设置相对定位以限制子元素位置 */
    position: relative;
}
div::before {
    content: '';
    width: 0;
    height: 0;
    border: 10px solid transparent;
    border-right: 10px solid #8d8dff;
    /* 父相子绝:子元素设置绝对定位在父元素中移动 */
    position: absolute;
    top: 20px;
    left: -20px;
}

为了更加美观,我加了一些文字居中、字体颜色等样式

以上代码在浏览器中的表现如下:

在这里插入图片描述

可以看到,带箭头的小气泡效果已经出来啦!

示例3 | 京东秒杀

在京东秒杀系统中有这样的一个平行四边形,我们一起来看一下:

在这里插入图片描述

思考下如果是上面的等腰三角形能否达到这样的效果?答案是否定的。这边的形状我们可以看成是中间一个矩形,边上两个直角三角形。问题来了:如何画一个直角三角形呢?

答案:给一个高和宽为0的盒子定义其中两条相邻的边,就可以得到两个直角三角形。

请看以下代码:

div {
    content: '';
    width: 0;
    height: 0;
    border-top: 100px solid pink;
    border-left: 50px solid blue;
}

我们在HTML中对一个div做以上样式规定,效果如下:

在这里插入图片描述

这时候只要将其中一个三角形设置为透明,就可以获得一个等腰直角三角形了。

下面我们来尝试下京东的案例,代码如下:

div {
    width: 300px;
    height: 100px;
    background-color: #8d8dff;
    position: relative;
    margin: 200px auto;
    color: #fff;
    text-align: center;
    line-height: 100px;
}
div::before {
    content: '';
    width: 0;
    height: 0;
    border-top: 100px solid pink;
    border-left: 50px solid transparent;
    position: absolute;
    left: -50px;
    top: 0;
}
div::after {
    content: '';
    width: 0;
    height: 0;
    border-top: 100px solid transparent;
    border-left: 50px solid blue;
    position: absolute;
    right: -50px;
    top: 0;
}

浏览器中效果如下:

在这里插入图片描述

这时候只要将三者的颜色修改一致,就可以得到一个平行四边形啦~

在这里插入图片描述

  • 29
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值