【CSS学习总结(一) CSS理解 & 选择器】

553 阅读20分钟

什么是CSS

层叠样式表(英语:Cascading Style Sheets,缩写:CSS;又称串样式列表、级联样式表、串接样式表、阶层式样式表)是一种用来为结构化文档(如HTML文档或XML应用)添加样式(字体、间距和颜色等)的计算机语言,由W3C定义和维护。

CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。

CSS 能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体字号样式,拥有对网页对象和模型样式编辑的能力。

以下引自维基百科

CSS不能单独使用,必须与HTML或XML一起协同工作,为HTML或XML起装饰作用。本文主要介绍用于装饰HTML网页的CSS技术。其中HTML负责确定网页中有哪些内容,CSS确定以何种外观(大小、粗细、颜色、对齐和位置)展现这些元素。CSS可以用于设定页面布局、设定页面元素样式、设定适用于所有网页的全局样式。CSS可以零散地直接添加在要应用样式的网页元素上,也可以集中化内置于网页、链接式引入网页以及导入式引入网页。

CSS最重要的目标是将文件的内容与它的显示分隔开来。在CSS出现前,几乎所有的HTML文件内都包含文件显示的信息,比如字体的颜色、背景应该是怎样的、如何排列、边缘、连线等等都必须一一在HTML文件内列出,有时重复列出。CSS使作者可以将这些信息中的大部分隔离出来,简化HTML文件,这些信息被放在一个辅助的,用CSS语言写的文件中。HTML文件中只包含结构和内容的信息,CSS文件中只包含样式的信息。

CSS初体验

我们使用HTML代码写出来的东西大部分都是非黑即白的,样式基本上不允许改变。

而使用CSS,我们能够为HTML写出来东西添加样式

我们在IDEA中创建一个 html文件,该文件中的代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>一级标题</h1>
</body>
</html>

有HTML基础的话,基本上扫一眼就能预览出该HTML文件在网页中的效果。

在日常生活中,我们点开一个一个的网页,可以发现有些网页上的文字存在颜色。

而我们通过 HTML写出来的文本内容基本上都是黑色

我们能不能使 h1标签中的内容改变颜色呢?

答案是可以的,而且非常简单!

我们在<head>标签体中添加一个<style></style>标签,标签中定义一个 h1开头的代码块(选择器),声明color并选择一个看着顺眼的颜色。

就像下面这样:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        h1{
            color: aqua;
        }
    </style>
</head>
<body>
<h1>一级标题</h1>
</body>
</html>

现在我们再次打开该 HTML文件,就会发现 h1标签中的内容改变颜色了

我们的世界终于不再是非黑即白了


上面算是简单的使用了CSS,但正常开发中我们一般不会将CSS代码直接像这样写入 html代码中

我们会将CSS代码放到专门的文件夹,达到 HTML和 CSS代码分离的效果。

就像这样:

但问题又来了,既然代码分离了 那如何使二者建立连接呢?

我们可以使用<link>标签来做到该功能。

<link rel="stylesheet" href="css/style.css"/>

<link>标签在使用tab补全后会存在一个 herf属性,该属性用于绑定我们css文件

这样即便 HTML代码和 CSS代码实现了分离 ,但CSS代码仍能对我们的 HTML内容进行样式的美化。

将 CSS和 HTML分离有什么好处呢?

  • 开发中,大部分情况下 CSS的代码量都会多于 HTML代码,如果我们不对其进行分离 HTML文件中全是 CSS代码 ,代码的可读性先不说,听着也不像那么回事不是么。
  • 分离后,HTML代码专注于写结构,而CSS代码专注于样式。二者都可以实现高复用,不是很棒么。
  • 分离后代码耦合性降低,会更便于维护。
  • 利用CSS中的重用、组合、继承等特性减少样式的代码量,样式结构上非常清晰。
  • ......

CSS的导入方式

我们上面有将CSS代码直接使用<style>标签写在 HTML文件内部,这种方式叫做内部样式

而将二者分离,使用<link>标签连接的方式叫做外部样式

除了这两种方式,我们还可以在 HTML标签内部添加一个style属性。在该属性中定义样式,这种方式叫做行内样式一般除了偷偷懒 尽量不要去这么写

<h1 style="color: aqua">一级标题</h1>

如果三种方式都使用的话就会存在优先级的问题

优先级存在就近原则,哪种方式离元素越近则优先使用哪种方式。

可以确定的是,如果有定义行内样式和其他样式,行内样式的优先级一般情况下一定会高于其他样式。因为他就定义在元素内部

而内部样式和外部样式一起定义的话,就要看谁离的近了。

选择器

在 CSS 中,选择器是一种模式,用于选择需要添加样式的元素。

选择器是CSS学习的重难点,会被非常非常频繁的被使用到。选择器的种类也非常之多

我们先来看看比较基础的选择器有哪些

  • 标签选择器
  • 类选择器
  • id选择器

首先看看使用过的标签选择器

标签选择器

标签选择器会选中所有为该标签的元素,为其添加样式。

我们在 html文件中有定义一个标签选择器,选中的是h1标签。

可以预见的是,三个h1标签中的文本样式将会被改变,而h2标签的文本样式则不会。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        h1{
            color: red;
        }
    </style>
</head>
<body>
<h1>h1-1</h1>
<h1>h1-2</h1>
<h1>h1-3</h1>
<h2>h2-1</h2>
</body>
</html>

这种选择器比较简单,也比较有局限性。

它无法做到为单个该标签改变样式的功能,它一改就是一整类标签。

类选择器

这种选择器功能更强大一些,它能为某一类元素添加样式。不限标签,只认类名。

但使用起来也相对比较麻烦一些,需要我们手动的在标签中添加 class属性

类选择器的定义有所改变,它使用 .class{} 的形式定义

我们在 html文件中定义一个类选择器,选中class属性为 first的元素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        .first{
            color: red;
        }
    </style>
</head>
<body>
<h1>h1-1</h1>
<h1 class="first">h1-2</h1>
<h1>h1-3</h1>
<h2 class="first">h2-1</h2>
</body>
</html>

选择器修改后,将只会有 class属性为 first的标签会被添加样式

ID选择器

这种选择器可以精准的为某一个特定id的元素添加样式,需要注意的是 id属性有全局唯一的特性 不允许重复。

这种选择器使用起来是最麻烦的,他的每一次使用意味着你需要定义一个新的id。

它使用 #id {}的形式定义

我们在 html文件中定义一个id选择器,选中id为 first的标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        #first{
            color: red;
        }
    </style>
</head>
<body>
<h1>h1-1</h1>
<h1 id="first">h1-2</h1>
<h1>h1-3</h1>
<h2>h2-1</h2>
</body>
</html>

id选择器无法做到像上面两种选择器一样,同时为多个元素添加样式(因为id全局唯一的特性)

虽然定义和使用都稍显麻烦,但这种选择器并不会因此而被束之高阁。它仍有它的可取之处,比如和其他选择器配合使用

既然有三种不同的选择器,如果我们都定义呢?优先级是如何?

<head>
	<style>
        #first{
            color: red;
        }
        .first{
            color: aquamarine;
        }
        h1{
            color: black;
        }
    </style>
</head>
<body>
<h1 class="first" id="first">h1-2</h1>
</body>

选择器的话就不会存在什么就近原则的情况了,它有固定的优先级。

优先级为: id选择器 > 类选择器 > 标签选择器

除了这些比较基础的选择器,还有各种各样不同应用场景的选择器等着我们

文档结构选择器

除了三种基础的选择器,还存在一些让人记起来比较痛苦的选择器,我们称之为文档结构选择器。因为它是按照标签的层次结构来进行元素的选择的

在正常的开发中,我们要写的标签会非常之多。可能会存在像如下代码这种标签中嵌套标签的情况

<body>
<p>我是第一层第一个</p>
<p>我是第一层第二个</p>
<p>我是第一层第三个</p>
<ul>
    <p>我是第二层第一个</p>
    <p>我是第二层第二个</p>
    <li>
        <p>我是第三层第一个</p>
        <p>我是第三层第二个</p>
        <p>我是第三层第三个</p>
    </li>
</ul>
</body>

如果我们只想选择第三层的全部p标签,该如何写选择器呢?

当然了,我们使用 id和 class的方式能够很快的完成这一操作。但你不想学点新东西吗?

后代选择器

又称派生选择器,后代选择器这个概念很好理解,我们带入辈分就好了。

  • 在最外面的<body>我们将其理解为曾祖父
  • 再往里就是第一层的<p>标签和<ul>标签了,我们将其理解为祖父
    • 再往里的话就是第二层<p>标签和<li>标签了,我们将其理解为父辈
      • 而第三层的<p>标签毫无疑问就是自己了(怎么感觉好像让代码占了便宜)

带入辈分后,我们想要选择第三层的全部p标签这一行为 就是选择父辈标签下的所有后代标签。

我们定义了这么多p标签,再使用p标签来作为父标签 定义后代选择器怕是要弄乱辈分。

所以我们只能使用<li>标签来作为父标签,定义后代选择器。

后代选择器的定义也很简单,父标签 空格 后代标签 {}

<style>
    li p{
        color: red;
    }
</style>

在上述 html代码中,我们使用了<li>标签来作为父标签,后代标签则是p标签。

这样的话,<li>标签下的所有p标签都会被选择器选中。

使用了后代选择器后,我们无论向内如何嵌套,只要存在相同的后代标签 这些后代标签就都会被选中。这就是后代选择器的特性

嵌套第四层第五层

可以看到,无论你如何嵌套,只要是在<li>标签之内p标签都会被视为其后代,继而被选择器选中。

子选择器

子选择器只选中父标签下的子标签。它只选中一类,再往下嵌套 孙子辈就不关它的事了。

子选择器的定义方式为 父标签 > 子标签 {}

我们在原代码的基础上进行修改,将<ul>标签作为父标签,子标签仍然为<p>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        ul>p{
            color: red;
        }
    </style>
</head>
<body>
<p>我是第一层第一个</p>
<p>我是第一层第二个</p>
<p>我是第一层第三个</p>
<ul>
    <p>我是第二层第一个</p>
    <p>我是第二层第二个</p>
    <li>
        <p>我是第三层第一个</p>
        <p>我是第三层第二个</p>
        <p>我是第三层第三个</p>
    </li>
</ul>
</body>
</html>

可以预见的,<ul>标签内为<p>的子标签会被选中,而再向内嵌套的<p>标签则不会被选中。这就是子选择器的特性

相邻兄弟选择器

相邻兄弟选择器能够选择一个相邻的同辈标签,但它只会向下选择。如果是在它上面的同辈标签,它就不会去管了。

相邻兄弟选择器的定义方式为: **指定标签 + 同辈标签 {} **

下列 html代码中,我们指定了第三层第二个<p>标签和它的一个同辈<p>标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        #first + p{
            color: red;
        }
    </style>
</head>
<body>
<p>我是第一层第一个</p>
<p>我是第一层第二个</p>
<p>我是第一层第三个</p>
<ul>
    <p>我是第二层第一个</p>
    <p>我是第二层第二个</p>
    <li>
        <p>我是第三层第一个</p>
        <p id="first">我是第三层第二个</p>
        <p>我是第三层第三个</p>
    </li>
</ul>
</body>
</html>

网页上的效果:

使用+定义相邻兄弟选择器后,它只允许存在一个兄弟标签 ,这个兄弟标签必须在它下面且需要相邻。

如果我们在被指定的标签兄弟标签中间,插入一个非兄弟标签的标签,那么相邻兄弟标选择器就会失效。

它并不会为插入的标签添加样式 或者继续向下寻找,这就是相邻兄弟选择器的特性。

<p id="first">我是第三层第二个</p>
<h5>如果我插足,样式就会失效</h5>
<p>我是第三层第三个</p>

可以看到,如果指定标签和兄弟标签不再相邻,那么相邻兄弟选择器就失效了。

一般兄弟选择器

但如果我们使用 ~ 替换 + 来定义选择器的话,就会允许存在多个兄弟标签了。

这样即便中间存在隔断也不要紧。他会继续向下寻找,但不会向上。这种选择器也叫同胞选择器。

定义方式为:指定标签 ~ 同辈标签 {}

#first ~ p{
    color: red;
}

这种选择器能够弥补相邻兄弟选择器的不足之处,即便和兄弟标签不相邻也不要紧,它会继续向下寻找兄弟标签这就是通用选择器的特性。

结构 伪类选择器

我们先来解释一下什么是伪类:

伪类是一种选择处于特定状态的选择器,其作用就是在文档的某部分添加了一个类,为我们提供更灵活、可维护的代码。

css 伪类是用于向某些选择器添加特殊的效果,是动态的,指当前元素所处的状态或者特性。只有一个元素达到一个特定状态时,它可能得到一个伪类的样式;当状态改变时,它又会失去这个样式。

我们可以理解成一个特定的CSS类,但与普通的类不一样,它只有处于DOM树无法描述的状态下才能为元素添加样式,所以将其称为伪类

大概理解了什么是伪类后,我们再看看什么叫 结构伪类选择器。

这个名词你不要把它连起来读 ,重点还是放在伪类选择器上。结构伪类选择器,顾名思义就是针对结构的伪类选择器。

当然这些概念性的东西不是我们的侧重点,我们更应该明白如何去使用才对。


首先仍然是需要你选中特定的元素,但这一次不让你使用 id 和 class。

需要选中的是第三层的第一个和最后一个p标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
    </style>
</head>
<body>
<p>我是第一层第一个</p>
<p>我是第一层第二个</p>
<p>我是第一层第三个</p>
<ul>
    <p>我是第二层第一个</p>
    <p>我是第二层第二个</p>
    <li>
        <p>我是第三层第一个</p>
        <p>我是第三层第二个</p>
        <p>我是第三层第三个</p>
        <p>我是第三层第四个</p>
    </li>
</ul>
</body>
</html>

如果不使用 id和 class属性,来选中这些特定的元素 实际上方法也是很多的。

这里我们使用 结构伪类选择器,这种选择器的定义很宽泛一般使用:指定标签 : 伪类 {} 的形式定义

我们在上述 html代码中定义一个结构伪类选择器

li p:first-child{
    color: red;
}

这样定义选择器后,<li>标签下的第一个子元素如果为<p>就会被选中

和相邻兄弟选择器一样,如果被隔断(不再是第一个子元素)。那该选择器也会失效,它并不会继续向下寻找第一个p标签为其添加样式

这也就是我们前面说的,**伪类具有动态性。 **它只会选中第一个子元素,如果标签不符合?那就不关它的事了。

<li>
    <h4>我来成为第一个元素</h4>
    <p>我是第三层第一个</p>
    <p>我是第三层第二个</p>
    <p>我是第三层第三个</p>
    <p>我是第三层第四个</p>
</li>

选中第三层最后一个p标签,选择器的具体定义也基本类似 我们只需要修改对应的伪类即可。

li p:last-child{
    color: red;
}

和上面一样,如果我们在末尾定义一个非p标签的子元素,它不再是最后一个子元素的话 该选择器也会失效。

<p>我是第三层第一个</p>
<p>我是第三层第二个</p>
<p>我是第三层第三个</p>
<p>我是第三层第四个</p>
<h4>我来成为最后一个元素</h4>


我们将上述代码进行修改,将第二层的p标签修改为 li标签。

在不使用 id和 class属性的同时,也不使用上述 伪类选择器。我们仍有办法能够选中第二层的第一个元素

<body>
<p>我是第一层第一个</p>
<p>我是第一层第二个</p>
<p>我是第一层第三个</p>
<ul>
    <li>我是第二层第一个</li>
    <li>我是第二层第二个</li>
    <li>
        <p>我是第三层第一个</p>
        <p>我是第三层第二个</p>
        <p>我是第三层第三个</p>
        <p>我是第三层第四个</p>
    </li>
</ul>
</body>

我们可以使用定位到其父元素的方式 来定义伪类选择器。

这种伪类选择器的定义方式为:**能够定位到父类的唯一子元素 : nth-child(x) {} **

这种选择器定义比较绕,我们修改p标签为 li标签就是为了满足定义条件。

因为p标签不是 能定义到其父类的唯一子元素,而修改后的 li标签则是。

我们能够通过 li标签来定位到它的父类<ul>标签,再通过<ul>标签来指定一个具体位置的子元素,该具体位置就是x。

我们尝试定义该伪类选择器

li:nth-child(1){
    color: red;
}

传入的x为1,也就是选中<ul>下第一个标签为<li>的子元素

该伪类选择器也属于那种不会向下穿透的选择器,但你可以通过修改 x 使其继续向下寻找指定位置的子元素

<ul>
    <h4>隔断</h4>
    <h4>隔断</h4>
    <li>我是第二层第一个</li>
    <li>我是第二层第二个</li>
    <li>

我们在 html代码中添加了两个h4标签作为隔断,这个时候我们想定位到第一个 li标签也不是没有办法,我们将x修改为3就好了。


当然了,想让其无视隔断也是能够做到的。我们只要将 nth-chhid修改为 nth-of-type即可。

这种选择器会通过 传入子元素标签类型来选中元素,如果是非该子元素标签(隔断),它会无视该元素 继续向下寻找规定的子元素标签

伪类是能够展开讲很久的知识点,我们篇幅也有限 不可能都讲。只会列出一些简单的

属性选择器

属性选择器非常强大,可以理解它为 id和 class的结合,它能使用大部分你能够想到的方式来选择指定的元素。

那么到底有多强大呢?我们一个一个来演示

我们将原本嵌套好几层的代码删掉,重新写一些带属性的简单标签。

<body>
<h3 id="h3.molu a" class="h3_first" title="fff">h3-1</h3>
<h3 id="h3.lin b" class="h3_second">h3-2</h3>
<h3 id="h3.zhang a" class="h3_end" title="eee">h3-3</h3>
<h4 id="h4.molu b" class="h4_first">h4-1</h4>
<h4 id="h4.lin a" class="h4_end" title="eeee">h4-2</h4>
</body>

属性选择器使用起来是非常灵活的,我们先来看第一个演示。

使用属性选择器,选中带有title属性的标签元素。选择器的定义为:

[title]{
    color: red;
}

由于存在h3和h4两类标签,我们就不需要在 []前面指定某一类标签了,我们直接省略不写,就是选择所有标签的意思。

[] 中指定一个属性,它就会为拥有该属性的所有标签添加样式。

这里我们指定的是 title属性,那么可以预见的: h3-1、h3-3以及h4-2这些文本会变成红色。


我们还可以在 []前面指定一类标签,只为该类标签中拥有title属性的元素添加样式

h3[title]{
    color: red;
}

我们这里写的是 h3,那为 h4标签的 h4-2文本就不会变成红色了。

我们还可以在指定标签后加一个空格,使其选择包含 title 属性的子元素。

演示之前我们需要添加一些子元素

<h3 id="h3.molu a" class="h3_first" title="fff">h3-1</h3>
<h3 id="h3.lin b" class="h3_second">h3-2</h3>
<h3 id="h3.zhang a" class="h3_end" title="eee">h3-3</h3>
<h3>
    <p title="fff">我是子元素p-1</p>
    <p>我是子元素p-2</p>
    <p title="eee">我是子元素p-3</p>
</h3>

我们对原先定义的属性选择器进行修改,在h3和[]之间加个空格

h3 [title]{
    /* h3和[]之间存在空格*/
    color: red;
}

修改后,h3标签的所有子元素只要存在title属性,就会为其添加样式


我们不仅可以指定属性,我们还可以指定属性的值。使其选择拥有这些值的属性元素

比如我们指定title属性为 eee的元素

h3 [title="eee"]{
    /* 
    这里h3和[]之间仍然存在空格,
    所以仍是在子元素中进行选择
    */
    color: red;
}

我们将空格去掉的话,就会在 h3标签中选择 title属性为 eee的元素了。

而将 h3也去掉,就会在 所有标签中(不包括子元素)选择 title属性为 eee的元素。


属性选择器十分强大,我们甚至可以使用类似模糊匹配的形式来选择元素

比如说我们选择 id属性中存在 字母a的元素

需要注意的是,这种模糊匹配只能匹配单词或者单个的字母,也就是使用空格进行分隔的。比如:h3.molu a

这种选择器的定义形式为:指定标签 [属性~="匹配的值"]{}

下列代码中未指定标签,也就是从全部标签中进行选择。我们可以根据需求来指定

[id~="a"]{
    color: red;
}


除了模糊匹配,我们还可以指定一个属性 选择拥有该属性且属性值后缀为 xxx的元素

比如指定 class属性,选择拥有 class属性且 class属性值以 _end为后缀的元素

我们的 h3和 h4标签中都存在拥有 class属性,且 class属性值以 _end结尾的元素。那么选择器定义后,这些元素会被添加样式。

该选择器的定义形式为:指定标签 [属性$="指定后缀"] {}

h3[class$="_end"]{
    color: red;
}

该选择器定义后,h3标签中所有 class以 _end结尾的元素都会被添加样式。


既然能指定属性值的后缀,那相对的也能够指定前缀

该选择器的定义形式为:指定标签 [属性^="指定前缀"] {}

[id^="h3.m"]{
    color: red;
}

该选择器定义后,所有标签中所有 id以 h3.m开头的元素都会被添加样式。


还有一种比较夸张的模糊匹配,它能够选中所有存在指定字符串的元素

比如说指定 id属性中存在 n的元素,我们 h3标签中 id属性中存在 n的元素就有两个。

<body>
<h3 id="h3.molu a" class="h3_first" title="fff">h3-1</h3>
<h3 id="h3.lin b" class="h3_second">h3-2</h3>
<h3 id="h3.zhang a" class="h3_end" title="eee">h3-3</h3>
<h3>
    <p title="fff">我是子元素p-1</p>
    <p>我是子元素p-2</p>
    <p title="eee">我是子元素p-3</p>
</h3>
<h4 id="h4.molu b" class="h4_first">h4-1</h4>
<h4 id="h4.lin a" class="h4_end" title="eeee">h4-2</h4>
</body>

该选择器的定义形式为:指定标签 [属性="匹配值"] {}*

通过上面的截图就能够了解到这种模糊匹配有多夸张了

定义后 h3标签中 所有 id属性存在 n字符串的元素都会被选中

写到这里不由惊呼,属性选择器是真的强大,记起来也是真的让人头大。

扩展

在定义属性时,有时候会存在大小写的问题,我们可以在[]中追加一个 i 来使大小写不敏感

这样的话,即便是大写的N,我们依旧能够匹配到


我们还可以定义多个条件,比如说 id中存在 n且class以 _end结尾的元素

多个条件的定义也不会很难,看一眼下面的代码基本上就能够明白。

[id*="n" i][class$="_end"]{
    color: red;
}

交集选择器

这种选择器比较简单,也比较实用。

我们对之前的代码进行一些修改

<h3 id="h3.moluN a" class="h3_first item active" title="fff">h3-1</h3>
<h3 id="h3.lin b" class="h3_second item">h3-2</h3>
<h3 id="h3.zhang a" class="h3_end active" title="eee">h3-3</h3>

它的定义方式为:.属性a. 属性b{}

需要注意的是,这些属性值必须以空格的形式分隔。

即选中class中即存在 a又存在 b的元素

.item.active{
    color: red;
}

并集选择器

该选择器听名字就知道和上面的交集选择器,定义或使用方式类似。

这种选择器的定义为:.属性a,.属性b{}

.h3_end,.item{
    color: red;
}

这种选择器定义后,class 属性值中存在 h3_enditem的元素都会被添加样式

放松一下眼睛

夹带私货(不是

原图P站地址

画师主页