CSS 简介
CSS(层叠样式表)是用于控制网页外观和布局的语言。理解 CSS 的核心概念——层叠、继承和优先级——是掌握 CSS 的关键。
什么是 CSS?
CSS 的作用
CSS(Cascading Style Sheets,层叠样式表)用于描述 HTML 文档的外观和格式:
- 颜色和背景:设置文字颜色、背景色、渐变等
- 字体和排版:控制字体、大小、行高、对齐方式
- 布局:控制元素的位置和排列方式
- 动画和过渡:创建动态效果
CSS 名称的含义
CSS 的名称本身就揭示了它的工作原理:
- Cascading(层叠):多个样式规则可以作用于同一个元素,按一定规则决定最终应用哪个
- Style Sheets(样式表):定义外观样式的规则集合
理解"层叠"二字是掌握 CSS 的关键。当你写 CSS 时,可能会遇到多个规则同时作用于同一个元素的情况,层叠规则决定了最终哪个样式会生效。
CSS 语法
基本结构
/* 选择器 */
h1 {
/* 属性: 值; */
color: blue;
font-size: 24px;
}
各部分说明:
h1 { color: blue; }
│ │ │
│ │ └── 值 (value)
│ └───────┘
│ │
│ └── 声明 (属性值对)
└───────────
选择器 (selector)
一个 CSS 规则由两部分组成:
- 选择器:指定要样式化的 HTML 元素
- 声明块:包含一个或多个声明,每个声明由属性和值组成
CSS 注释
/* 这是单行注释 */
/*
* 这是多行注释
* 用于详细说明样式规则
*/
/* 不要使用 HTML 风格的注释 */
/* <!-- 这不是正确的CSS注释 --> */
注释在 CSS 中非常重要,可以帮助你:
- 解释代码的功能和目的
- 临时禁用某些样式进行调试
- 为团队协作提供文档
CSS 引入方式
1. 外部样式表(推荐)
将 CSS 写入单独的 .css 文件,通过 <link> 引入:
<!-- 在 HTML 的 <head> 中引入 -->
<head>
<link rel="stylesheet" href="styles.css">
</head>
styles.css:
h1 {
color: blue;
font-size: 24px;
}
为什么推荐外部样式表?
- 样式与结构分离:HTML 负责结构,CSS 负责样式,各司其职
- 多页面共享:一个 CSS 文件可以应用于多个页面
- 浏览器缓存:CSS 文件会被缓存,提高页面加载速度
- 易于维护:修改样式只需要改一个文件
路径说明:
<!-- CSS 文件与 HTML 在同一目录 -->
<link rel="stylesheet" href="styles.css">
<!-- CSS 文件在子目录中 -->
<link rel="stylesheet" href="css/styles.css">
<!-- CSS 文件在上一级目录 -->
<link rel="stylesheet" href="../styles.css">
2. 内部样式表
将 CSS 写在 HTML 文件的 <style> 标签内:
<head>
<style>
h1 {
color: blue;
}
p {
font-size: 16px;
}
</style>
</head>
适用场景:
- 单页面网站
- 需要针对特定页面添加特殊样式
- 无法修改外部 CSS 文件的情况
缺点:
- 多页面网站需要重复编写
- 增加 HTML 文件体积
- 无法利用浏览器缓存
3. 内联样式(慎用)
直接在 HTML 元素的 style 属性中编写:
<h1 style="color: blue; font-size: 24px;">标题</h1>
<p style="font-size: 16px; color: #333;">段落内容</p>
为什么避免使用内联样式?
- 样式与 HTML 混合,难以维护
- 无法复用样式
- 优先级最高,难以覆盖
- 增加 HTML 文件体积
例外情况:
- 某些 CMS 只允许编辑 HTML body
- HTML 邮件需要兼容各种客户端
- JavaScript 动态设置的样式
CSS 层叠(Cascade)
层叠是 CSS 最核心的概念,它决定了当多个样式规则作用于同一元素时,哪个规则最终会生效。
层叠的工作原理
当多个 CSS 规则应用于同一个元素时,浏览器会按照以下顺序(重要性从低到高)决定最终应用的样式:
- 来源和重要性
- 优先级(Specificity)
- 源码顺序
来源类型
CSS 可以来自不同来源,按优先级从低到高排列:
| 来源 | 说明 |
|---|---|
| 用户代理样式 | 浏览器默认样式 |
| 用户样式 | 用户自定义的样式 |
| 作者样式 | 开发者编写的样式 |
| 作者 !important | 开发者标记为重要的样式 |
| 用户 !important | 用户标记为重要的样式 |
| 用户代理 !important | 浏览器默认的重要样式 |
实际影响:
/* 浏览器默认样式 */
a {
color: blue;
text-decoration: underline;
}
/* 开发者样式会覆盖浏览器默认样式 */
a {
color: #333;
text-decoration: none;
}
源码顺序
当两个规则的优先级相同时,后出现的规则会覆盖先出现的规则:
/* 两个规则优先级相同(都是元素选择器) */
h1 {
color: red;
}
h1 {
color: blue; /* 这个会生效 */
}
这个规则也适用于外部样式表的引入顺序:
<!-- 后引入的样式表会覆盖先引入的 -->
<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="styles.css"> /* styles.css 中的规则优先 */
CSS 优先级(Specificity)
优先级是浏览器用来决定哪个 CSS 声明会被应用到元素上的算法。理解优先级是解决"样式不生效"问题的关键。
优先级计算:ID-CLASS-TYPE 方法
优先级用一个三列数值表示:ID-CLASS-TYPE
| 列 | 包含的选择器 | 每个的权重 |
|---|---|---|
| ID | #id | 1-0-0 |
| CLASS | .class、[attr]、:pseudo-class | 0-1-0 |
| TYPE | element、::pseudo-element | 0-0-1 |
计算规则:
- 从左到右比较,ID 列数值大的优先级更高
- ID 相同时,比较 CLASS 列
- CLASS 也相同时,比较 TYPE 列
- 三列都相同时,后出现的规则优先
优先级计算示例
/* 优先级: 0-0-1 */
h1 {
color: red;
}
/* 优先级: 0-1-0(class 比 element 高) */
.title {
color: blue;
}
/* 优先级: 1-0-0(id 最高) */
#main-title {
color: green;
}
更复杂的例子:
/* 优先级: 0-0-1 */
a {
color: black;
}
/* 优先级: 0-1-1(一个 class + 一个 element) */
.nav a {
color: blue;
}
/* 优先级: 1-1-1(一个 id + 一个 class + 一个 element) */
#header .nav a {
color: red; /* 最终生效 */
}
优先级对照表
| 选择器 | ID | CLASS | TYPE | 总计 |
|---|---|---|---|---|
h1 | 0 | 0 | 1 | 0-0-1 |
h1 + p::first-letter | 0 | 0 | 3 | 0-0-3 |
.nav a | 0 | 1 | 1 | 0-1-1 |
#header .nav a | 1 | 1 | 1 | 1-1-1 |
#identifier | 1 | 0 | 0 | 1-0-0 |
button:not(#mainBtn) | 1 | 0 | 1 | 1-0-1 |
特殊情况
通用选择器和组合器不增加优先级:
/* 优先级: 0-0-1(* 不计算) */
* {
margin: 0;
}
/* 优先级: 0-1-1(> 不计算) */
.nav > a {
color: blue;
}
:is()、:has()、:not() 的优先级:
这三个伪类本身不增加优先级,但它们内部的参数会:
/* 优先级取参数中最高的:1-0-0 */
:is(#header, .nav) a {
color: red;
}
/* 相当于 #header a 的优先级 */
:where() 的优先级始终为 0:
/* 优先级: 0-0-0(:where 不增加优先级) */
:where(#header) a {
color: red;
}
内联样式和 !important
内联样式的优先级高于所有选择器:
<!-- 内联样式优先级最高(可以理解为 1-0-0-0) -->
<h1 style="color: red;">标题</h1>
!important 会覆盖所有正常声明:
/* 正常声明 */
h1 {
color: blue;
}
/* !important 声明优先级最高 */
h1 {
color: red !important; /* 最终生效 */
}
!important 会打破正常的层叠规则,使代码难以维护。只在确实需要覆盖第三方库样式时使用,并添加注释说明原因。
优先级最佳实践
- 避免使用 ID 选择器:优先级过高,难以覆盖
- 避免使用内联样式:难以维护和覆盖
- 避免使用 !important:打破层叠规则
- 使用类选择器:优先级适中,灵活可控
/* 不推荐:ID 选择器优先级过高 */
#header {
background: blue;
}
/* 推荐:使用类选择器 */
.header {
background: blue;
}
CSS 继承
继承是指某些 CSS 属性会从父元素传递到子元素。理解继承可以帮助你写出更简洁的 CSS。
哪些属性会继承?
会继承的属性(主要与文本相关):
- 字体相关:
font-family、font-size、font-weight、font-style - 文本相关:
color、text-align、line-height、letter-spacing、word-spacing - 列表相关:
list-style - 其他:
visibility、cursor
不会继承的属性(主要与盒模型相关):
- 盒模型:
width、height、margin、padding、border - 布局:
display、position、float、clear - 背景:
background、background-color、background-image - 其他:
overflow、z-index
理解继承的原因:
想象一下,如果 border 会继承,那么给父元素设置边框后,所有子元素都会出现边框,这显然不是我们想要的效果。CSS 的设计者让文本相关属性继承,而盒模型相关属性不继承,是经过深思熟虑的。
继承示例
<div class="parent">
<p>这段文字会继承父元素的颜色和字体</p>
<p>这段文字也会继承</p>
</div>
.parent {
color: #333;
font-family: Arial, sans-serif;
/* border 不会继承到子元素 */
border: 1px solid #ddd;
}
控制继承
CSS 提供了四个特殊值来控制继承行为:
inherit:强制继承
.parent {
border: 1px solid red;
}
.child {
/* 强制继承父元素的 border */
border: inherit;
}
initial:重置为初始值
.parent {
color: red;
}
.child {
/* 重置为 color 的初始值(通常是黑色) */
color: initial;
}
unset:自然重置
/* 如果属性默认继承,则继承;否则重置为初始值 */
.child {
color: unset; /* color 默认继承,所以会继承父元素 */
border: unset; /* border 默认不继承,所以重置为初始值 */
}
revert:恢复为浏览器默认
/* 恢复为浏览器的默认样式 */
a {
color: revert; /* 恢复为浏览器的链接颜色(通常是蓝色) */
}
使用 all 属性重置所有
/* 重置元素的所有属性 */
.reset {
all: unset; /* 所有属性都重置 */
all: initial; /* 所有属性都设为初始值 */
all: inherit; /* 所有属性都继承 */
all: revert; /* 所有属性都恢复浏览器默认 */
}
CSS 选择器
选择器用于指定要样式化的 HTML 元素。CSS 提供了丰富的选择器类型。
基本选择器
元素选择器(类型选择器)
/* 选择所有段落元素 */
p {
color: #333;
}
/* 选择所有标题 */
h1, h2, h3 {
color: #2c3e50;
}
类选择器
/* HTML 中定义 class="highlight" */
.highlight {
background-color: yellow;
}
/* 元素+类选择器(更具体) */
p.highlight {
font-weight: bold;
}
ID 选择器
/* HTML 中定义 id="header" */
#header {
background-color: #3498db;
padding: 20px;
}
- ID 在页面中应该是唯一的
- 类选择器比 ID 选择器更灵活,推荐使用类
- ID 选择器优先级过高,可能导致样式难以覆盖
组合选择器
后代选择器(空格)
/* 选择 article 内的所有段落(包括嵌套的) */
article p {
line-height: 1.6;
}
子选择器(>)
/* 只选择直接子元素 */
ul > li {
list-style: none;
}
相邻兄弟选择器(+)
/* 选择紧跟在 h1 后面的 p */
h1 + p {
font-size: 1.2em;
}
通用兄弟选择器(~)
/* 选择 h1 后面所有的同级 p */
h1 ~ p {
color: gray;
}
伪类选择器
伪类用于选择元素的特定状态:
/* 鼠标悬停 */
a:hover {
color: #e74c3c;
}
/* 链接状态 */
a:link { color: blue; } /* 未访问 */
a:visited { color: purple; } /* 已访问 */
/* 表单状态 */
input:focus {
border-color: #3498db;
}
input:disabled {
opacity: 0.5;
}
/* 结构伪类 */
li:first-child { font-weight: bold; }
li:last-child { border-bottom: none; }
li:nth-child(odd) { background: #f5f5f5; }
li:nth-child(3n+1) { color: red; }
伪元素选择器
伪元素用于选择元素的特定部分:
/* 在元素前插入内容 */
.quote::before {
content: '"';
color: gray;
}
/* 在元素后插入内容 */
.quote::after {
content: '"';
color: gray;
}
/* 首行样式 */
p::first-line {
font-weight: bold;
}
/* 首字母样式 */
p::first-letter {
font-size: 2em;
float: left;
}
属性选择器
/* 有特定属性的元素 */
[disabled] {
opacity: 0.5;
}
/* 属性等于特定值 */
input[type="text"] {
border: 1px solid #ccc;
}
/* 属性包含特定值 */
[class~="btn"] {
padding: 10px 20px;
}
/* 属性以特定值开头 */
[href^="https"] {
color: green;
}
/* 属性以特定值结尾 */
[href$=".pdf"] {
background: url('pdf-icon.png');
}
现代选择器
:is() 匹配任意
/* 选择 article、section 或 aside 内的 h2 */
:is(article, section, aside) h2 {
color: #333;
}
:where() 优先级为 0
/* 与 :is() 相同,但优先级为 0-0-0 */
:where(article, section, aside) h2 {
color: #333;
}
:has() 父选择器
/* 选择包含 img 的 a 元素 */
a:has(img) {
display: block;
}
/* 选择包含 focus 状态子元素的 form */
form:has(:focus) {
border-color: blue;
}
CSS 属性和值
常用属性示例
/* 文字颜色 */
color: #333333;
color: rgb(0, 0, 0);
color: red;
/* 字体大小 */
font-size: 16px;
font-size: 1.2em;
/* 背景 */
background-color: #f5f5f5;
background-image: url('bg.jpg');
background: linear-gradient(to bottom, #fff, #000);
/* 边框 */
border: 1px solid #333;
border-radius: 5px;
/* 外边距 */
margin: 10px;
margin-top: 20px;
/* 内边距 */
padding: 15px;
padding-left: 20px;
/* 宽度和高度 */
width: 100%;
height: 200px;
max-width: 1200px;
CSS 函数值
CSS 提供了许多内置函数来计算值:
calc() 计算
.box {
/* 宽度为父元素的 100% 减去 30px */
width: calc(100% - 30px);
/* 高度为视口高度减去头部高度 */
height: calc(100vh - 60px);
}
min() 和 max()
/* 取较小值 */
.sidebar {
width: min(300px, 30%);
}
/* 取较大值 */
.main {
width: max(600px, 70%);
}
clamp() 范围限制
/* 最小 1rem,首选 2.5vw,最大 2rem */
h1 {
font-size: clamp(1rem, 2.5vw, 2rem);
}
transform 变换函数
.box {
/* 旋转 */
transform: rotate(45deg);
/* 缩放 */
transform: scale(1.5);
/* 移动 */
transform: translateX(100px);
transform: translateY(50px);
transform: translate(100px, 50px);
}
简写属性
简写属性可以同时设置多个相关属性的值:
/* padding 简写 */
padding: 10px; /* 四边相同 */
padding: 10px 20px; /* 上下 左右 */
padding: 10px 20px 15px; /* 上 左右 下 */
padding: 10px 20px 15px 25px; /* 上 右 下 左(顺时针) */
/* margin 简写 */
margin: 10px 20px;
/* border 简写 */
border: 1px solid #333;
/* background 简写 */
background: #fff url('bg.jpg') no-repeat center center;
/* font 简写 */
font: italic bold 16px/1.5 Arial, sans-serif;
/* 风格 粗细 大小/行高 字体 */
CSS 单位
长度单位
| 单位 | 类型 | 说明 | 示例 |
|---|---|---|---|
px | 绝对 | 像素 | font-size: 16px; |
% | 相对 | 相对于父元素 | width: 50%; |
em | 相对 | 相对于当前字体大小 | font-size: 1.5em; |
rem | 相对 | 相对于根元素字体大小 | font-size: 1rem; |
vw | 相对 | 视口宽度的 1% | width: 50vw; |
vh | 相对 | 视口高度的 1% | height: 100vh; |
ch | 相对 | 字符"0"的宽度 | width: 60ch; |
推荐使用场景
/* 布局尺寸:使用 % 或 vw */
.container {
width: 100%;
max-width: 1200px;
}
/* 字体大小:使用 rem */
html {
font-size: 16px;
}
h1 {
font-size: 2rem; /* 32px */
}
p {
font-size: 1rem; /* 16px */
}
/* 组件内部的相对尺寸:使用 em */
.button {
padding: 0.5em 1em;
font-size: 1rem;
}
.button-large {
font-size: 1.25rem; /* padding 自动按比例增大 */
}
/* 全屏布局:使用 vh */
.hero {
height: 100vh;
}
颜色值
/* 颜色名称 */
color: red;
color: blue;
/* 十六进制 */
color: #ff0000;
color: #f00; /* 简写 */
/* RGB/RGBA */
color: rgb(255, 0, 0);
color: rgba(255, 0, 0, 0.5); /* 带透明度 */
/* HSL */
color: hsl(0, 100%, 50%);
color: hsla(0, 100%, 50%, 0.5);
/* 现代颜色函数 */
color: oklab(0.7 0.1 0.1);
color: oklch(70% 0.2 150);
CSS 变量
CSS 变量(自定义属性)允许你定义可复用的值:
定义和使用
/* 定义变量 */
:root {
--primary-color: #3498db;
--font-size-base: 16px;
--spacing: 10px;
}
/* 使用变量 */
.button {
background-color: var(--primary-color);
font-size: var(--font-size-base);
padding: var(--spacing);
}
/* 带默认值的变量 */
.content {
color: var(--text-color, #333); /* 如果 --text-color 未定义,使用 #333 */
}
变量的作用域
/* 全局变量 */
:root {
--color: blue;
}
/* 局部变量 */
.card {
--card-padding: 20px;
padding: var(--card-padding);
}
变量的优势
- 减少重复:定义一次,多处使用
- 语义化:
--primary-color比#3498db更容易理解 - 便于维护:修改一处即可全局更新
- 主题切换:轻松实现深色/浅色主题
@ 规则
@ 规则(at-rules)是 CSS 的特殊指令。
@media 媒体查询
/* 响应式设计 */
body {
font-size: 16px;
}
@media (min-width: 768px) {
body {
font-size: 18px;
}
}
@layer 层叠层
/* 定义层的顺序 */
@layer reset, base, components, utilities;
/* 在层中定义样式 */
@layer base {
h1 {
font-size: 2rem;
}
}
@layer components {
.button {
padding: 10px 20px;
}
}
@import 导入
/* 导入外部样式表 */
@import url('reset.css');
@import url('fonts.css');
浏览器开发者工具
浏览器开发者工具是学习和调试 CSS 的利器:
打开方式
- Chrome/Edge:按
F12或Ctrl+Shift+I - Firefox:按
F12或Ctrl+Shift+I - Safari:
Cmd+Option+I
常用功能
- Elements 面板:查看和编辑 HTML 和 CSS
- Styles 面板:查看计算后的样式
- Computed 面板:查看盒模型的精确值
- 选择器测试:点击元素快速定位
- 使用开发者工具实时修改 CSS,即时预览效果
- 查看元素的 computed styles 了解最终应用的样式
- 使用
:hov强制显示伪类状态(如 hover) - 样式被划掉表示被覆盖,可以查看是被哪个规则覆盖的
第一个 CSS 示例
HTML 结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS 入门</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="site-header">
<h1>我的网站</h1>
<nav>
<a href="#">首页</a>
<a href="#">教程</a>
<a href="#">关于</a>
</nav>
</header>
<main>
<article>
<h2>欢迎学习 CSS</h2>
<p class="intro">CSS 用于控制网页的样式和布局。</p>
<p>通过 CSS,我们可以让网页变得更加美观。</p>
</article>
</main>
<footer>
<p>© 2024 我的网站</p>
</footer>
</body>
</html>
CSS 样式
/* style.css */
/* CSS 变量定义 */
:root {
--primary-color: #2c3e50;
--accent-color: #3498db;
--text-color: #333;
--light-bg: #f9f9f9;
}
/* 重置默认样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 基本样式 */
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
line-height: 1.6;
color: var(--text-color);
background-color: var(--light-bg);
}
/* 头部样式 */
.site-header {
background-color: var(--primary-color);
color: white;
padding: 20px;
}
.site-header h1 {
margin-bottom: 10px;
}
/* 导航样式 */
nav a {
color: white;
text-decoration: none;
margin-right: 15px;
}
nav a:hover {
text-decoration: underline;
}
/* 主内容区 */
main {
max-width: 800px;
margin: 30px auto;
padding: 0 20px;
}
article h2 {
color: var(--primary-color);
margin-bottom: 15px;
}
.intro {
font-size: 18px;
color: #555;
}
/* 底部样式 */
footer {
background-color: var(--primary-color);
color: white;
text-align: center;
padding: 20px;
margin-top: 50px;
}
小结
本章学习了 CSS 的核心概念:
- CSS 基础:CSS 的作用和语法结构
- 引入方式:外部样式表、内部样式表、内联样式
- 层叠:多个规则作用于同一元素时的决定机制
- 优先级:ID-CLASS-TYPE 计算方法
- 继承:哪些属性会继承,如何控制继承
- 选择器:元素、类、ID、伪类、伪元素、属性选择器
- 单位和值:长度单位、颜色值、CSS 变量
- @ 规则:@media、@layer、@import
- 开发工具:浏览器开发者工具的使用
理解层叠、优先级和继承这三个概念,是解决大多数 CSS 问题的关键。当你发现样式没有按预期生效时,首先检查优先级,然后检查继承,最后检查源码顺序。
练习
- 创建第一个 CSS 文件,设置页面基本样式
- 尝试使用不同的选择器选择元素,比较它们的优先级
- 使用浏览器开发者工具检查和修改样式
- 定义 CSS 变量并在多个地方使用
- 创建一个简单的博客页面布局样式
- 练习优先级计算:写出以下选择器的优先级
#header .nav aul > li:first-child.container .item:where(#main) .content