前言
作为前端开发三剑客之一的CSS(层叠样式表),很容易掌握和使用,这也导致很多人疏忽了对于它的底层基础,今天我们就来学习一下css的底层基础。
CSS规则
css规则,也称css规则集(css rule set),是定义如何对html文档中的元素进行样式化的基础结构。一个完整的css规则是由选择器(Selector) 和声明块(Declaration Block) 组成。选择器指定了要应用样式的HTML元素,声明块包含了具体样式的定义。每个声明块内部是由一个个 声明(Declarations) 组成的,每个声明又分为属性(Property)和值(Value),中间用冒号(:)分隔,声明之间用分号(;)分隔。
/*这是一个css规则*/
h1{ /*选择器*/
color:red; /*声明*/
text-align:center; /*声明*/
}
那么css是如何引入的呢?主要分为三种方式:
1.外部样式表
<head> <link rel="stylesheet" href="styles.css"> </head>
这是我们在实际运用中最常用到的一种方式,可以将样式代码集中管理,易于维护和更新,并且可以通过缓存提高页面加载速度。对于大型项目来说,这是推荐的做法。
2.内部样式表
<head>
<style>
h1 {
color: red;
}
</style>
</head>
也就是直接在中引入,这种作法只适合对于单个html文档进行样式设置。
3.内联样式
<p style="color: red;">这是一个红色的段落。</p>
内联样式是直接在HTML标签中使用style属性定义样式。这种方式适用于对单个元素进行快速样式设置,但是不建议多用,会降低代码的可读性。
那么我们为什么要把css写在头部或者标签内部呢?是因为浏览器会先解析HTML文档来构建dom树,dom树上的一个个节点就是我们的标签,在构建dom树时,遇到css文件,下载样式构建CSSOM(CSS对象模型),CSSOM是一个树状结构,描述了所有样式规则及其优先级。然后会将css和html结合得到一个渲染树,最终得到页面。如果在标签内容之后再导入css那么我们首先会看到的是一个个单独的标签元素,没有任何的样式。
选择器的优先级
在我们对同一个标签设置多个css规则时,它的优先级是如何来排序的呢?
<div id="main" class="container">
<p>猜猜我是什么颜色</p>
</div>
/* 1 */
p {
color: blue;
}
/* 101 */
#main p {
color: green;
}
/* 11 */
.container p {
color: red;
}
在这里面我们用了标签,类和id来选择p标签,优先级是一个计算规则,最大的数就会优先显示,标签是1分,类是10分,id则是100分,所以显然,上面段落文字显示的就是绿色了。但是人外有人天外有天,如果你使用内联样式在标签内部添加style,那么它的得分将会是1000分。
<p style="color:pink;">猜猜我是什么颜色</p>
这时候就会是粉色了,但是!!!还有一个王炸,那就是!important,他才是最大的,10000分。
p {
color: blue !important;
}
蓝色了。
当我们在遇到复杂的选择器时也完全不用慌,只要用加法全部加起来就好了,但是要记住,选择器一定只会选择最后的元素!
.container ul li:nth-child(odd) /*10+1+1+10 = 22*/
最后选中了为位于 .container 类的 内的 <ul> 列表中的奇数位置的 <li> 元素。
选择器的分类
1.基础选择器
- 标签选择器 顾名思义就是标签
- 类选择器 格式为:.+类名
- id选择器 格式为:#+id 每个标签的id是唯一的这也是为啥他是100 因为查找快
- 通配符选择器
*选择所有的标签
2.组合选择器
<body>
<div class="container">
<h1>标题</h1>
<p>这是第一段文字</p>
<p>这是第二段文字</p>
<a href="">链接</a>
<span>这是一个span元素</span>
<div class="inner">
<p>这是一个内部的段落</p>
</div>
</div>
</body>
/* 相邻兄弟选择器 */
h1 + p{
color: red;
}
- 相邻兄弟选择器,通过
+号连接,只会选择跟在第一个元素后的第二个元素,且两个元素必须是同一级的。
- 普通兄弟选择器,通过
~号连接,他会选择跟在第一个标签之后的所有第二个标签,同样他们需要是同级的。
/* 普通兄弟选择器 */
h1 ~ p{
color: blue;
}
诶,有没有注意到第一行的也变成蓝色了,他们的优先级相同,所以不是优先级的问题,那么我们就知道了,在优先级相同的情况下,谁后出现,那么就会覆盖掉前面的样式。
- 子元素选择器,会选择跟在第一个标签后的所有子元素
/* 子元素选择器 */
.container > p{
text-decoration: underline;
}
注意只是子元素,不包含孙元素等之后的元素。
- 后代元素选择器,会选择第一个标签后所有第二个标签的后代,包括子,孙,孙孙,孙孙孙....
/* 后代元素选择器 */
.container p{
color: green;
}
三个p标签中文字全部变成了绿色。
- 伪类选择器,只要可交互状态的标签都可以使用伪类选择器来添加样式。
<body>
<div class="container">
<h1>伪类选择器示例</h1>
<button>点击我</button>
<p>鼠标悬浮在这里</p>
<input type="text" placeholder="输入框">
<input type="checkbox" id="option1">
<label for="option1">选项1</label>
<input type="checkbox" id="option2" checked>
<label for="option2">选项2</label>
</div>
</body>
<style>
/* 伪类选择器示例 */
button:active {
background-color: red;
color: #fff;
}
p:hover {
background-color: yellow;
}
input:checked + label {
color: blue;
}
</style>
当我点击按钮时:
标悬浮在p标签上时
勾选了跟在input属性后的标签属性时
- 伪类元素器,伪元素选择器用于选择元素的特定部分。通常用
::来表示,其也可以用:表示,但是为了和伪类选择器区分我们通常用两个冒号
::selection{
background-color: blue;
color: #fff;
}
元素被选中后
- 属性选择器,属性选择器用于根据元素的属性及其值来选择元素。它们使得我们可以更加精细地控制样式应用,而无需依赖类或ID。属性选择器在处理表单元素、链接、图像等带有特定属性的元素时特别有用。
<!-- attribute 属性 -->
<div id="main" class="container">
<a href="">这是一个链接</a>
</div>
id class href都是标签的属性,使用的格式则为:
input[type="text"] {
width: 200px;
}
这个规则会选择所有 type 属性等于 "text" 的 <input> 元素,并设置其宽度为 200px。
a[href^="https"] {
color: green;
}
这个规则会选择所有 href 属性以 "https" 开头的 <a> 元素,并将其文本颜色设置为绿色。
nth-child vs nth-of-type
最后我们来讲一个容易混淆的点,就是nth-child和nth-of-type,先来看例子
<body>
<div class="container">
<h1>nth-child vs nth-of-type 例子</h1>
<p>这是一个段落</p>
<div>这是一个div</div>
<p>这是第二个段落</p>
<p>这是第三个段落</p>
<div>这是第二个div</div>
</div>
</body>
/* 顺序 */
.container p:nth-child(3){
background-color: yellow;
color: black;
}
/* of-type */
.container p:nth-of-type(3){
background-color: lightblue;
color: black;
}
诶,这是我们页面呈现的效果,是不是很疑惑为什么没有黄色,那是因为nth-child更加注重的是顺序,他的选择的是.container容器下子元素为第三个的元素,很显然他第三个子元素是div而不是p那我们在这里加上了p之后他就会失去效果,如果我们将p删掉:
黄色就出来了,对于nth-of-type它更加注重的是类型,它选择的是位于.container下的第三个p标签,而不是按照顺序来选择,这在面试中非常容易混淆,请大家牢牢记住。