跳到主要内容

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 规则由两部分组成:

  1. 选择器:指定要样式化的 HTML 元素
  2. 声明块:包含一个或多个声明,每个声明由属性和值组成

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 规则应用于同一个元素时,浏览器会按照以下顺序(重要性从低到高)决定最终应用的样式:

  1. 来源和重要性
  2. 优先级(Specificity)
  3. 源码顺序

来源类型

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#id1-0-0
CLASS.class[attr]:pseudo-class0-1-0
TYPEelement::pseudo-element0-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; /* 最终生效 */
}

优先级对照表

选择器IDCLASSTYPE总计
h10010-0-1
h1 + p::first-letter0030-0-3
.nav a0110-1-1
#header .nav a1111-1-1
#identifier1001-0-0
button:not(#mainBtn)1011-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

!important 会打破正常的层叠规则,使代码难以维护。只在确实需要覆盖第三方库样式时使用,并添加注释说明原因。

优先级最佳实践

  1. 避免使用 ID 选择器:优先级过高,难以覆盖
  2. 避免使用内联样式:难以维护和覆盖
  3. 避免使用 !important:打破层叠规则
  4. 使用类选择器:优先级适中,灵活可控
/* 不推荐:ID 选择器优先级过高 */
#header {
background: blue;
}

/* 推荐:使用类选择器 */
.header {
background: blue;
}

CSS 继承

继承是指某些 CSS 属性会从父元素传递到子元素。理解继承可以帮助你写出更简洁的 CSS。

哪些属性会继承?

会继承的属性(主要与文本相关):

  • 字体相关:font-familyfont-sizefont-weightfont-style
  • 文本相关:colortext-alignline-heightletter-spacingword-spacing
  • 列表相关:list-style
  • 其他:visibilitycursor

不会继承的属性(主要与盒模型相关):

  • 盒模型:widthheightmarginpaddingborder
  • 布局:displaypositionfloatclear
  • 背景:backgroundbackground-colorbackground-image
  • 其他:overflowz-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:按 F12Ctrl+Shift+I
  • Firefox:按 F12Ctrl+Shift+I
  • SafariCmd+Option+I

常用功能

  1. Elements 面板:查看和编辑 HTML 和 CSS
  2. Styles 面板:查看计算后的样式
  3. Computed 面板:查看盒模型的精确值
  4. 选择器测试:点击元素快速定位
调试技巧
  • 使用开发者工具实时修改 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>&copy; 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 的核心概念:

  1. CSS 基础:CSS 的作用和语法结构
  2. 引入方式:外部样式表、内部样式表、内联样式
  3. 层叠:多个规则作用于同一元素时的决定机制
  4. 优先级:ID-CLASS-TYPE 计算方法
  5. 继承:哪些属性会继承,如何控制继承
  6. 选择器:元素、类、ID、伪类、伪元素、属性选择器
  7. 单位和值:长度单位、颜色值、CSS 变量
  8. @ 规则:@media、@layer、@import
  9. 开发工具:浏览器开发者工具的使用

理解层叠、优先级和继承这三个概念,是解决大多数 CSS 问题的关键。当你发现样式没有按预期生效时,首先检查优先级,然后检查继承,最后检查源码顺序。

练习

  1. 创建第一个 CSS 文件,设置页面基本样式
  2. 尝试使用不同的选择器选择元素,比较它们的优先级
  3. 使用浏览器开发者工具检查和修改样式
  4. 定义 CSS 变量并在多个地方使用
  5. 创建一个简单的博客页面布局样式
  6. 练习优先级计算:写出以下选择器的优先级
    • #header .nav a
    • ul > li:first-child
    • .container .item
    • :where(#main) .content