前言
CSS (Cascading Style Sheets) 是网页设计的核心语言之一,用于描述HTML文档的呈现方式。本文将全面介绍CSS的基础概念、各种选择器类型及其使用方法、注意事项,以及选择器权重的重要性。
一、CSS基础概念
1. CSS基本结构
CSS由三个主要部分组成:
- 选择器(Selector) :用于选择要样式化的HTML元素
- 声明(Declaration) :一个属性与值的键值对
- 声明块(Declaration Block) :由大括号
{}
包围的一组声明
p {
color: blue;
font-size: 16px;
}
在这个例子中:
p
是选择器color: blue;
和font-size: 16px;
都是声明- 整个
{color: blue; font-size: 16px;}
是声明块 - 选择器加上声明块构成一个规则集(ruleset)
2. CSS层叠特性
CSS中的"C"代表"层叠"(Cascading),这意味着:
- 样式可以来自多个来源(作者样式、用户样式、浏览器默认样式)
- 当规则冲突时,会根据特定规则确定哪个样式生效
- 层叠顺序决定了最终应用的样式(权重相同的话)
二、CSS选择器详解
CSS选择器是用于选择HTML元素的模式。了解各种选择器及其用法是掌握CSS的关键。
1. 基本选择器
元素选择器(类型选择器/标签选择器)
选择特定类型的HTML元素。
p {
color: blue;
}
类选择器(Class选择器)
选择具有特定class属性的元素,以.
开头,一个元素可以有多个类名,一个类名也可以用于多个元素。
.container {
width: 80%;
}
ID选择器
选择具有特定id属性的元素,以#
开头,ID在文档中应该是唯一的。
#main {
background-color: #f0f0f0;
}
通用选择器(通配符选择器)
通用选择器匹配文档中的所有元素,以*
开头,通常用于重置默认样式或设置全局样式。下面这个样式常用来去除所有元素默认内外边距。
* {
margin: 0; /* 外边距*/
padding: 0;/* 内边距*/
}
2. 组合选择器
后代选择器 (空格)
选择.container
元素内部的所有<p>
后代元素,无论嵌套多深。
.container p {
color: red;
}
子元素选择器 (>
)
仅选择.container
直接子元素的<p>
,不包含更深层级的。
.container > p {
color: blue;
}
相邻兄弟选择器 (+
)
选择紧接在<h2>
后面的第一个<p>
兄弟元素。
h2 + p {
font-weight: bold;
}
通用兄弟选择器 (~
)
选择<h2>
之后的所有同级<p>
元素。
h2 ~ p {
background: yellow;
}
并集选择器 (,)
同时选择所有<h1>
, <h2>
和<h3>
元素。
h1, h2, h3 {
font-family: sans-serif;
}
经典面试错误点:
- 混淆后代和子选择器:很多人误以为
div p
和div > p
效果相同,实际上前者选择所有后代,后者只选直接子元素。(相当于前者可以选择儿子和孙子无穷无尽,而后者只能选择儿子)- 相邻兄弟选择器误解:
A + B
只选择紧邻的下一个兄弟,而不是所有后续兄弟。- 选择器优先级混淆:组合选择器的优先级计算常被误解,如
.class p
比单纯的p
选择器优先级高。- 性能问题:过度嵌套的后代选择器如
div ul li a
会影响页面渲染性能。- 空格敏感:
div > p
和div>p
效果相同,但div >p
在某些旧浏览器中可能有问题。
3. 伪类选择器
伪类用于定义元素的特殊状态。
行为伪类
:hover
- 鼠标悬停时:active
- 元素被激活时(如点击按钮):focus
- 元素获得焦点时
button:hover {
background-color: red;
}
input:focus {
border: 2px solid blue;
}
状态伪类
:checked
- 选中的表单元素:disabled
- 禁用的表单元素
input:checked + label {
font-weight: bold;
}
结构伪类
:first-child
- 第一个子元素:last-child
- 最后一个子元素:nth-child(n)
- 第n个子元素:nth-of-type(n)
- 第n个特定类型的子元素
li:nth-child(odd) {
background-color: lightgray;
}
.container :nth-child(3) {
background-color: yellow;
}
.container p:nth-of-type(3) {
background-color: red;
}
注意: :nth-child
和:nth-of-type
的区别:
:nth-child
选择父元素的第n个子元素,不考虑类型:nth-of-type
选择父元素的第n个特定类型的子元素
这个是面试中常考的点,下面我们通过一个案例来解释一下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>:nth-child vs :nth-of-type</title>
<style>
/* 基础样式 */
.container {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
/* 使用:nth-child选择器 */
.container p:nth-child(2) {
color: red;
font-weight: bold;
}
/* 使用:nth-of-type选择器 */
.container p:nth-of-type(2) {
background-color: yellow;
}
/* 辅助样式,使效果更明显 */
p, div, span {
padding: 5px;
margin: 5px 0;
}
</style>
</head>
<body>
<div class="container">
<div>我是第一个子元素(div)</div>
<p>我是第二个子元素(第一个p元素)</p>
<span>我是第三个子元素(span)</span>
<p>我是第四个子元素(第二个p元素)</p>
<p>我是第五个子元素(第三个p元素)</p>
<div>我是第六个子元素(div)</div>
</div>
</body>
</html>
在这个例子中:
-
:nth-child(2)
选择器:- 这个是从1开始计算,不是从0开始
.container p:nth-child(2)
他会选择container
类的第2个子元素,并且他必须是p
标签,如果不是,那么这个元素不会被渲染.container:nth-child(2)
这个就不用考虑第2个子元素是不是p
标签了
-
:nth-of-type(2)
选择器:- 选择父元素中第2个特定类型(p)的子元素
- 它会跳过非p元素,只计算p元素的顺序
- 在我们的例子中,第2个p元素是
<p>我是第四个子元素(第二个p元素)</p>
总结:
选择器 | 计算方式 | 上例中选中的元素 |
---|---|---|
:nth-child(2) | 所有子元素中的第2个(还要注意前面有没有加上限定) | 第二个子元素(第一个p元素) |
:nth-of-type(2) | 同类型子元素中的第2个 | 第二个p元素(第四个总体子元素) |
否定伪类 (:not
)
选择不匹配给定选择器的元素。
li:not(:last-child) {
margin-bottom: 10px;
}
4. 伪元素选择器
伪元素用于样式化元素的特定部分。
::before
- 在元素内容前插入内容::after
- 在元素内容后插入内容::selection
- 用户选中的文本部分
::selection {
background-color: blue;
color: white;
}
面试考题:伪类和伪元素的区别:
核心区别
特性 | 伪类(Pseudo-classes) | 伪元素(Pseudo-elements) |
---|---|---|
作用对象 | 元素的状态 | 元素的某部分或生成内容 |
语法 | 单冒号 : (如 :hover ) | 双冒号 :: (如 ::before ) |
典型用例 | :active , :nth-child() | ::before , ::first-line |
记忆技巧
- 伪类(Pseudo-class)→ “类”似状态(如悬停、选中)。
- 伪元素(Pseudo-element)→ “元素的一部分” (如首字母、插入内容)。
通过区分它们的作用(状态 vs. 部分/内容)和语法(:
vs. ::
),可以更清晰地运用它们。
三、选择器权重与优先级(面试常考)
CSS选择器的权重(也称为特异性)决定了当多个规则应用于同一个元素时,哪个规则会被应用。理解选择器权重是解决样式冲突的关键。
选择器权重等级
CSS选择器的权重由四个组成部分构成,可以表示为:(a, b, c, d)
从左到右权重依次减弱:
- 内联样式 (a): 直接在HTML元素的style属性中编写的样式
- ID选择器 (b): 使用#id选择的元素
- 类/属性/伪类选择器 (c): 包括.class、[type="text"]、:hover等
- 元素/伪元素选择器 (d): 包括div、p、::before等
各类选择器的具体权重值
权重规则:
a > b > c > d
选择器类型 | 权重值 (a,b,c,d) | 示例 |
---|---|---|
内联样式 | (1,0,0,0) | <div style="color:red"> |
ID选择器 | (0,1,0,0) | #header |
类选择器 | (0,0,1,0) | .active |
属性选择器 | (0,0,1,0) | [type="text"] |
伪类选择器 | (0,0,1,0) | :hover |
元素选择器 | (0,0,0,1) | div |
伪元素选择器 | (0,0,0,1) | ::before |
通配符(*) | (0,0,0,0) | * |
继承的样式 | 无权重 | 从父元素继承的样式 |
优先级规则
- !important > 内联样式 > ID选择器 > 类/属性/伪类选择器 > 元素/伪元素选择器
- 相同权重下,后定义的样式会覆盖前面的样式
- 继承的样式权重最低,低于任何直接应用的样式
特殊情况
-
!important: 会覆盖所有其他规则(尽量避免使用)
-
通用选择器(*) 、组合器(+, >, ~) 和 :not()伪类:
- 没有权重
- 组合器不影响权重
- :not()本身的权重为0,但括号内选择器的权重会计算
-
相同权重时,后定义的样式优先
结语
CSS选择器是前端开发的基础工具,掌握各种选择器及其权重对于编写可维护、高效的CSS代码至关重要。通过合理组合不同类型的选择器,可以精确地定位和样式化页面元素,同时保持代码的灵活性和可扩展性。记住,选择器的使用不仅仅是让样式生效,还要考虑性能、可维护性和团队协作的便利性。