什么是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_end
和 item
的元素都会被添加样式
放松一下眼睛
夹带私货(不是