Appearance
✨ CSS 层叠 👌
1. 层叠概述
层叠(Cascade) 是 CSS 的核心机制之一,用于解决样式声明冲突的问题。
1.1 什么是层叠
层叠是浏览器决定当多个 CSS 规则应用到同一个元素时,哪个规则最终生效的过程。它通过一套严格的优先级规则来自动处理样式冲突。
1.2 层叠的重要性
- 解决冲突:当多个样式规则作用于同一元素时,确定最终应用的样式
- 可预测性:提供一套明确的规则,让开发者能够预测样式的最终效果
- 灵活性:允许样式的覆盖和继承,提高代码的可维护性
2. 声明冲突
2.1 什么是声明冲突
声明冲突:同一个 CSS 属性,通过不同的选择器多次应用到同一个元素上。
2.2 冲突产生的场景
html
<!DOCTYPE html>
<html>
<head>
<style>
/* 场景1:不同选择器设置相同属性 */
p {
color: blue;
}
.text {
color: red;
}
#content {
color: green;
}
/* 场景2:同一选择器重复声明 */
.box {
width: 100px;
width: 200px; /* 后面的会覆盖前面的 */
}
/* 场景3:外部样式表与内部样式冲突 */
h1 {
font-size: 24px;
}
</style>
<link rel="stylesheet" href="external.css" />
</head>
<body>
<p class="text" id="content">这段文字的颜色是什么?</p>
<div class="box">这个盒子的宽度是多少?</div>
</body>
</html>2.3 冲突解决机制
浏览器通过层叠算法来解决冲突,按照以下顺序进行比较:
- 重要性(Importance)
- 特殊性(Specificity)
- 源次序(Source Order)
3. 重要性比较
3.1 重要性层级
重要性从高到低的顺序:
- 作者样式表中的 !important 样式
- 作者样式表中的普通样式
- 浏览器默认样式表中的样式
3.2 样式表类型详解
3.2.1 作者样式表(Author Stylesheet)
开发者编写的样式,包括:
css
/* 内联样式 */
<div style="color: red;">内联样式</div>
/* 内部样式表 */
<style>
.text { color: blue; }
</style>
/* 外部样式表 */
<link rel="stylesheet" href="style.css">3.2.2 用户代理样式表(User Agent Stylesheet)
浏览器的默认样式:
css
/* 浏览器默认样式示例 */
h1 {
display: block;
font-size: 2em;
margin-top: 0.67em;
margin-bottom: 0.67em;
font-weight: bold;
}
p {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}4. 特殊性比较
4.1 特殊性计算规则
特殊性通过四位数字 (a, b, c, d) 来表示:
| 位置 | 权重 | 计算规则 | 示例 |
|---|---|---|---|
| a | 千位 | 内联样式数量 | style="color: red" |
| b | 百位 | ID 选择器数量 | #header |
| c | 十位 | 类、属性、伪类选择器数量 | .btn, [type="text"], :hover |
| d | 个位 | 元素、伪元素选择器数量 | div, ::before |
4.2 特殊性计算示例
css
/* 示例1:(0, 0, 0, 1) */
p {
color: black;
}
/* 示例2:(0, 0, 1, 0) */
.text {
color: blue;
}
/* 示例3:(0, 1, 0, 0) */
#title {
color: red;
}
/* 示例4:(0, 0, 1, 1) */
p.text {
color: green;
}
/* 示例5:(0, 1, 1, 1) */
#title p.text {
color: purple;
}
/* 示例6:(0, 0, 2, 2) */
div.container p.text {
color: orange;
}
/* 示例7:(0, 0, 1, 0) */
[class="text"] {
color: yellow;
}
/* 示例8:(0, 0, 2, 0) */
.text:hover {
color: pink;
}
/* 示例9:(0, 0, 0, 2) */
div::before {
content: "";
}
/* 示例10:(1, 0, 0, 0) */
/* <div style="color: red;"> 内联样式 */5.3 复杂选择器计算
css
/* 复杂示例分析 */
/* (0, 1, 1, 3) */
#header .nav ul li a {
/* 1个ID + 1个类 + 3个元素 */
}
/* (0, 0, 4, 2) */
.sidebar .menu li:first-child a:hover {
/* 2个类 + 2个伪类 + 2个元素 */
}
/* (0, 2, 1, 1) */
#header #nav .logo span {
/* 2个ID + 1个类 + 1个元素 */
}5.4 特殊性比较规则
css
/* 比较示例 */
.text {
color: blue;
} /* (0, 0, 1, 0) */
p {
color: red;
} /* (0, 0, 0, 1) */
/* 结果:蓝色胜出,因为 (0, 0, 1, 0) > (0, 0, 0, 1) */
#title {
color: green;
} /* (0, 1, 0, 0) */
.text.highlight {
color: yellow;
} /* (0, 0, 2, 0) */
/* 结果:绿色胜出,因为 (0, 1, 0, 0) > (0, 0, 2, 0) */::: important
重要:特殊性比较是逐位比较,不是数值相加!
:::
5.5 通配符和组合器
css
/* 通配符选择器特殊性为 0 */
* {
color: black;
} /* (0, 0, 0, 0) */
/* 组合器不增加特殊性 */
div > p {
color: blue;
} /* (0, 0, 0, 2) */
div + p {
color: red;
} /* (0, 0, 0, 2) */
div ~ p {
color: green;
} /* (0, 0, 0, 2) */
/* :not() 伪类本身不计算,但其参数计算 */
:not(.text) {
color: yellow;
} /* (0, 0, 1, 0) */6. 源次序比较
6.1 源次序规则
当重要性和特殊性都相同时,后声明的样式会覆盖先声明的样式。
css
/* 示例:相同特殊性的规则 */
.text {
color: red;
} /* 先声明 */
.text {
color: blue;
} /* 后声明,会覆盖红色 */
p {
font-size: 14px;
} /* 先声明 */
p {
font-size: 16px;
} /* 后声明,会覆盖 14px */6.2 样式表加载顺序
html
<!DOCTYPE html>
<html>
<head>
<!-- 1. 第一个外部样式表 -->
<link rel="stylesheet" href="reset.css" />
<!-- 2. 第二个外部样式表 -->
<link rel="stylesheet" href="main.css" />
<!-- 3. 内部样式表 -->
<style>
.text {
color: blue;
}
</style>
</head>
<body>
<!-- 4. 内联样式(特殊性最高) -->
<p class="text" style="color: red;">文本内容</p>
</body>
</html>6.3 爱恨法则(LVHA)
链接伪类的正确顺序:
css
/* 正确的顺序:LoVe HAte */
a:link {
color: blue;
} /* L - Link */
a:visited {
color: purple;
} /* V - Visited */
a:hover {
color: red;
} /* H - Hover */
a:active {
color: orange;
} /* A - Active */7. 实际应用
7.1 重置样式表
7.1.1 什么是重置样式表
重置样式表用于覆盖浏览器的默认样式,确保在不同浏览器中获得一致的显示效果。
7.1.2 常见的重置样式表
1. Reset.css(激进重置)
css
/* Eric Meyer's Reset CSS */
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}2. Normalize.css(温和重置)
css
/* Normalize.css 部分示例 */
html {
line-height: 1.15;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
font-size: 100%;
line-height: 1.15;
margin: 0;
}3. 自定义重置样式
css
/* 现代化的重置样式 */
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-size: 16px;
line-height: 1.5;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: #333;
background-color: #fff;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0 0 1rem 0;
font-weight: bold;
line-height: 1.2;
}
p {
margin: 0 0 1rem 0;
}
ul,
ol {
margin: 0 0 1rem 0;
padding-left: 2rem;
}
img {
max-width: 100%;
height: auto;
}
button {
cursor: pointer;
border: none;
background: none;
font: inherit;
}7.1.3 重置样式表的使用
html
<!DOCTYPE html>
<html>
<head>
<!-- 1. 首先加载重置样式表 -->
<link rel="stylesheet" href="reset.css" />
<!-- 2. 然后加载自定义样式 -->
<link rel="stylesheet" href="main.css" />
</head>
<body>
<!-- 页面内容 -->
</body>
</html>7.2 组件样式设计
按钮组件示例
css
/* 基础按钮样式 */
.btn {
display: inline-block;
padding: 0.5rem 1rem;
border: 1px solid transparent;
border-radius: 0.25rem;
font-size: 1rem;
line-height: 1.5;
text-align: center;
text-decoration: none;
cursor: pointer;
transition: all 0.3s ease;
}
/* 主要按钮 */
.btn-primary {
color: white;
background-color: #007bff;
border-color: #007bff;
}
.btn-primary:hover {
background-color: #0056b3;
border-color: #004085;
}
/* 次要按钮 */
.btn-secondary {
color: white;
background-color: #6c757d;
border-color: #6c757d;
}
/* 大尺寸按钮 */
.btn-lg {
padding: 0.75rem 1.5rem;
font-size: 1.25rem;
}
/* 小尺寸按钮 */
.btn-sm {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
}8. 最佳实践建议
8.1 层叠管理策略
8.1.1 避免过度使用 !important
css
/* 不推荐:滥用 !important */
.bad-practice {
color: red !important;
font-size: 16px !important;
margin: 10px !important;
}
/* 推荐:合理的选择器设计 */
.component .header .title {
color: red;
font-size: 16px;
margin: 10px;
}8.1.2 使用合理的选择器特殊性
css
/* 不推荐:特殊性过高 */
#header #nav #menu .item .link {
color: blue;
}
/* 推荐:适中的特殊性 */
.nav-link {
color: blue;
}
.nav-link.active {
color: red;
}8.2 代码组织原则
8.2.1 样式表加载顺序
html
<!-- 推荐的加载顺序 -->
<head>
<!-- 1. 重置样式 -->
<link rel="stylesheet" href="reset.css" />
<!-- 2. 第三方库 -->
<link rel="stylesheet" href="bootstrap.css" />
<!-- 3. 基础样式 -->
<link rel="stylesheet" href="base.css" />
<!-- 4. 组件样式 -->
<link rel="stylesheet" href="components.css" />
<!-- 5. 页面特定样式 -->
<link rel="stylesheet" href="page.css" />
</head>8.2.2 CSS 架构方法
1. BEM 方法论
css
/* Block Element Modifier */
.card {
} /* Block */
.card__header {
} /* Element */
.card__body {
} /* Element */
.card--large {
} /* Modifier */
.card__header--highlighted {
} /* Element + Modifier */2. OOCSS 原则
css
/* 结构与皮肤分离 */
.btn {
/* 结构样式 */
display: inline-block;
padding: 0.5rem 1rem;
border-radius: 0.25rem;
}
.btn-primary {
/* 皮肤样式 */
background-color: #007bff;
color: white;
}
.btn-secondary {
/* 皮肤样式 */
background-color: #6c757d;
color: white;
}8.3 性能考虑
8.3.1 CSS 文件优化
css
/* 合并相似规则 */
.btn-primary,
.btn-secondary,
.btn-success {
/* 共同样式 */
display: inline-block;
padding: 0.5rem 1rem;
border-radius: 0.25rem;
}
/* 使用 CSS 变量减少重复 */
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--border-radius: 0.25rem;
}
.btn {
border-radius: var(--border-radius);
}