03.CSS与响应式设计
1. CSS是什么?为什么需要它?
1.1 从"白纸"到"彩色画":HTML与CSS的关系
还记得我们在第二章学的HTML吗?HTML就像是一张白纸上的文字,告诉你"这里有个标题"、"那里有段文字",但所有的文字都是黑色、同样大小、没有颜色。
生活类比: - HTML = 房子的框架结构(墙、门、窗) - CSS = 房子的装修风格(墙纸颜色、家具摆放、灯光效果)
实际例子:
只有HTML的网页(像白纸): 1
2
3<h1>我的博客</h1>
<p>欢迎来到我的网站</p>
<p>这里有很多有趣的内容</p>
加上CSS后的网页(像彩色画): 1
2
3<h1 style="color: blue; font-size: 32px;">我的博客</h1>
<p style="color: gray; line-height: 1.6;">欢迎来到我的网站</p>
<p style="color: gray; line-height: 1.6;">这里有很多有趣的内容</p>
💡 关键理解:
HTML负责"内容是什么",CSS负责"内容长什么样"。
就像写作文:HTML是"写什么",CSS是"怎么写漂亮"。
1.2 CSS的诞生:从"混乱"到"统一"
历史背景(1990s-1996)
在CSS出现之前,网页设计师们遇到了大麻烦:
| 问题 | 当时的解决方案 | 为什么不好 |
|---|---|---|
| 样式混乱 | 每个网站用不同的HTML标签实现样式 | 代码重复,维护困难 |
| 无法复用 | 每个页面都要重新写样式代码 | 改一个颜色要改100个地方 |
| HTML臃肿 | 用<font>、<center>等标签控制样式 |
HTML代码变得又长又乱 |
真实案例: 1
2
3
4
5<!-- 1990年代的网页代码(没有CSS) -->
<font color="red" size="5"><center><b>欢迎来到我的网站</b></center></font>
<font color="blue" size="3">这里有很多内容</font>
<font color="blue" size="3">还有更多内容</font>
<!-- 每个地方都要重复写样式,改颜色要改100次! -->
CSS的诞生(1996年)
1996年,W3C(万维网联盟)发布了CSS 1.0,彻底改变了网页设计:
| CSS的优势 | 说明 | 实际效果 |
|---|---|---|
| 样式分离 | 样式写在单独的CSS文件中 | HTML代码变简洁,CSS代码可复用 |
| 统一管理 | 改一个CSS文件,全站样式都变 | 改颜色只需改1个地方 |
| 专业分工 | 前端设计师专注CSS,后端专注HTML | 开发效率提升10倍 |
现代代码(有CSS): 1
2
3
4<!-- HTML:只负责结构 -->
<h1>欢迎来到我的网站</h1>
<p>这里有很多内容</p>
<p>还有更多内容</p>
1 | /* CSS:统一管理样式 */ |
🌟 历史意义:
CSS的诞生让网页设计从"手工作坊"变成了"现代化工厂",是Web开发史上的重要里程碑。
1.3 为什么CSS对现代Web开发至关重要?
| 重要性 | 说明 | 实际案例 |
|---|---|---|
| 用户体验 | 美观的界面吸引用户 | 同样功能的网站,设计好的访问量高3倍 |
| 维护效率 | 统一管理样式,修改方便 | 改主题颜色从"改100个文件"变成"改1个文件" |
| 响应式设计 | 让网页适配手机、平板、电脑 | 一个网站,所有设备都能看 |
| 性能优化 | CSS可以缓存,加载更快 | 用户第二次访问时,页面加载快50% |
💡 对初学者的意义:
学会CSS,你就能做出专业、美观、现代的网页。
这是从"能写代码"到"能做好看的产品"的关键一步!
2. CSS选择器:精准定位的"瞄准镜"
2.1 什么是选择器?
生活类比:
想象你是一个园丁,花园里有100朵花,你想给"红色的玫瑰花"浇水。
- ❌ 没有选择器:你只能一朵一朵地找,找到红色玫瑰再浇水(效率低)
- ✅ 有选择器:你直接说"给所有红色玫瑰浇水",系统自动找到所有符合条件的(效率高)
CSS选择器 = 告诉浏览器"我要给哪些元素加样式"
2.2 基础选择器(必须掌握)
2.2.1 标签选择器(元素选择器)
作用:选中所有相同标签的元素
语法:直接写标签名
1 | /* 选中所有 <p> 标签 */ |
实际例子: 1
2
3<p>这是第一段</p>
<p>这是第二段</p>
<h1>这是标题</h1>
效果:所有<p>标签的文字变成蓝色,所有<h1>标签的字号变成32px
💡 适用场景:给所有相同类型的元素设置统一样式(比如所有段落都用同样的字体大小)
2.2.2 类选择器(最常用)
作用:选中所有具有相同class属性的元素
语法:.类名(注意前面有个点)
1 | /* 选中所有 class="highlight" 的元素 */ |
实际例子: 1
2
3<p class="highlight">这段文字会被高亮</p>
<p>这段文字不会被高亮</p>
<button class="button">点击我</button>
效果:只有class="highlight"的段落背景变黄,只有class="button"的按钮有蓝色背景
💡 为什么最常用?
因为可以精确控制:不是所有段落都要高亮,只有特定的才需要。
就像给特定的人发消息,而不是群发所有人。
2.2.3 ID选择器
作用:选中具有特定id属性的元素(注意:一个页面中,同一个id只能出现一次)
语法:#id名(注意前面有个井号)
1 | /* 选中 id="header" 的元素 */ |
实际例子: 1
2
3<header id="header">网站头部</header>
<main>主要内容</main>
<footer id="footer">网站底部</footer>
效果:只有id="header"的元素有深色背景,只有id="footer"的元素有浅色背景
⚠️ 重要提醒:
- ID是唯一的:一个页面中,同一个id只能出现一次(就像身份证号,每个人只有一个)
- 类可以重复:一个页面中,同一个class可以出现多次(就像"学生"这个身份,很多人都有)
- 什么时候用ID?:页面中唯一的元素(如header、footer、导航栏)
- 什么时候用类?:页面中可能重复的元素(如按钮、卡片、列表项)
2.2.4 属性选择器
作用:根据元素的属性及其值来选中元素
语法:[属性名="属性值"]
1 | /* 选中所有 type="text" 的输入框 */ |
实际例子: 1
2
3
4<input type="text" placeholder="输入用户名">
<input type="password" placeholder="输入密码">
<a href="http://example.com">外部链接</a>
<a href="/about">内部链接</a>
效果:只有文本输入框有边框,只有外部链接是蓝色
💡 适用场景:
当你想选中"具有特定属性的元素"时使用(比如所有外部链接、所有必填输入框)
2.3 组合选择器(进阶技巧)
2.3.1 后代选择器(空格)
作用:选中某个元素内部的所有指定元素(不管嵌套多少层)
语法:父元素 子元素
1 | /* 选中 .container 内部的所有 <p> 标签 */ |
实际例子: 1
2
3
4
5
6
7<div class="container">
<p>这个段落会被选中</p>
<div>
<p>这个段落也会被选中(即使嵌套在div里)</p>
</div>
</div>
<p>这个段落不会被选中(不在.container里)</p>
效果:只有.container内部的段落变成蓝色,外部的段落不变
2.3.2 子元素选择器(>)
作用:选中某个元素的直接子元素(只选一层,不选嵌套的)
语法:父元素 > 子元素
1 | /* 只选中 .container 的直接子元素 <p> */ |
实际例子: 1
2
3
4
5
6<div class="container">
<p>这个段落会被选中(直接子元素)</p>
<div>
<p>这个段落不会被选中(不是直接子元素)</p>
</div>
</div>
对比: -
后代选择器(空格):选中所有嵌套的<p>(包括间接子元素)
-
子元素选择器(>):只选中直接子元素<p>(不包括间接子元素)
2.3.3 并集选择器(逗号)
作用:同时选中多个不同的元素,给它们设置相同的样式
语法:选择器1, 选择器2, 选择器3
1 | /* 同时选中 h1、h2、h3,给它们设置相同的样式 */ |
实际例子: 1
2
3
4<h1>标题1</h1>
<h2>标题2</h2>
<h3>标题3</h3>
<p>段落</p>
效果:所有标题(h1、h2、h3)都变成蓝色加粗,段落不变
2.4 伪类选择器(让交互更生动)
什么是伪类?
伪类选择器用于选中元素的特定状态(比如鼠标悬停、被点击、第一个子元素等)
2.4.1 常用伪类
| 伪类 | 作用 | 示例 |
|---|---|---|
:hover |
鼠标悬停时的状态 | 按钮悬停时变色 |
:active |
鼠标点击时的状态 | 按钮按下时的效果 |
:focus |
元素获得焦点时 | 输入框被选中时 |
:first-child |
第一个子元素 | 列表第一项特殊样式 |
:nth-child(n) |
第n个子元素 | 列表奇数项特殊样式 |
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26/* 链接默认样式 */
a {
color: blue;
text-decoration: none;
}
/* 鼠标悬停时 */
a:hover {
color: red;
text-decoration: underline;
}
/* 鼠标点击时 */
a:active {
color: green;
}
/* 列表第一项 */
li:first-child {
font-weight: bold;
}
/* 列表奇数项 */
li:nth-child(odd) {
background-color: #f0f0f0;
}
HTML示例: 1
2
3
4
5
6
7<a href="#">点击我试试</a>
<ul>
<li>第一项(会加粗)</li>
<li>第二项</li>
<li>第三项(会有背景色)</li>
<li>第四项</li>
</ul>
效果: - 链接默认蓝色,鼠标悬停变红色并加下划线,点击时变绿色 - 列表第一项加粗,奇数项有浅灰色背景
💡 为什么叫"伪类"?
因为它不是真正的HTML类(class),而是元素的"状态"。
就像人的"状态":健康、生病、疲劳,不是人的属性,而是某个时刻的状态。
2.5 选择器优先级(重要概念)
2.5.1 什么是优先级?
当多个选择器选中同一个元素,且设置了不同的样式时,浏览器需要决定"听谁的"。
优先级规则(从高到低): 1.
内联样式(style="...") - 优先级最高 2.
ID选择器(#id) 3.
类选择器(.class)、属性选择器([attr])、伪类(:hover)
4. 标签选择器(p、div等)
实际例子: 1
<p class="text" id="intro" style="color: green;">这是一段文字</p>
1 | p { |
最终效果:文字是绿色(因为内联样式优先级最高)
💡 记忆技巧:
优先级就像"权力等级":
- 内联样式 = 皇帝(最高权力)
- ID选择器 = 大臣(高权力)
- 类选择器 = 官员(中等权力)
- 标签选择器 = 平民(基础权力)
2.6 实战练习:用选择器美化页面
任务:给下面的HTML添加CSS,实现以下效果: -
所有段落文字为灰色 - 所有.highlight类的元素背景为黄色 -
所有链接默认蓝色,悬停时变红色 - 列表第一项加粗
HTML代码: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
<head>
<title>选择器练习</title>
<style>
/* 在这里写CSS */
</style>
</head>
<body>
<h1>我的网页</h1>
<p>这是一段普通文字</p>
<p class="highlight">这是一段高亮文字</p>
<a href="#">点击我</a>
<ul>
<li>第一项</li>
<li>第二项</li>
<li>第三项</li>
</ul>
</body>
</html>
参考答案: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25/* 所有段落文字为灰色 */
p {
color: gray;
}
/* 所有 .highlight 类的元素背景为黄色 */
.highlight {
background-color: yellow;
}
/* 所有链接默认蓝色 */
a {
color: blue;
text-decoration: none;
}
/* 链接悬停时变红色 */
a:hover {
color: red;
}
/* 列表第一项加粗 */
li:first-child {
font-weight: bold;
}
🌟 记住:
选择器是CSS的"瞄准镜",学会精准定位,你就能控制网页的每一个细节!
3. Flex布局实战:让元素"听话"的魔法
3.1 为什么需要Flex布局?
3.1.1 传统布局的痛点
还记得我们之前学的HTML吗?当我们把几个<div>放在一起时,它们会垂直排列(一个在另一个下面),就像叠积木一样。
问题来了:如果我们想让它们横向排列(并排显示),比如做一个导航栏,该怎么办?
传统方法(很麻烦): 1
2
3
4
5
6
7
8
9
10
11/* 方法1:使用float(浮动) */
.nav-item {
float: left; /* 让元素"浮起来",横向排列 */
}
/* 问题:需要清除浮动,容易出bug */
/* 方法2:使用inline-block */
.nav-item {
display: inline-block; /* 让块级元素变成行内块 */
}
/* 问题:元素之间会有空隙,难以控制 */
💡 生活类比:
传统布局就像"手动摆积木":
- 想横向排列?得用各种"技巧"(float、inline-block)
- 想居中?得算数学(margin: 0 auto)
- 想对齐?得写很多代码Flex布局就像"智能积木盒":
- 说一句"横向排列",所有积木自动排好
- 说一句"居中",自动居中
- 简单、直观、强大!
3.1.2 Flex布局的诞生(2012年)
2012年,W3C正式发布了Flexbox布局规范,彻底改变了CSS布局方式:
| 传统布局 | Flex布局 |
|---|---|
| 需要写很多代码 | 几行代码搞定 |
| 容易出bug(如浮动塌陷) | 稳定可靠 |
| 难以实现复杂对齐 | 轻松实现各种对齐 |
| 响应式适配困难 | 天然支持响应式 |
🌟 历史意义:
Flex布局是CSS布局史上的革命性突破,让"居中"、"对齐"这些曾经让人头疼的问题,变得像写一句话那么简单。
3.2 Flex布局的核心概念
3.2.1 什么是Flex容器和Flex项目?
生活类比:
想象一个收纳盒(Flex容器),里面放着几个小盒子(Flex项目)。
- Flex容器:设置了
display: flex;的元素(就像收纳盒) - Flex项目:Flex容器内的直接子元素(就像小盒子)
实际例子: 1
2
3
4
5<div class="container"> <!-- 这是Flex容器 -->
<div class="item">项目1</div> <!-- 这是Flex项目 -->
<div class="item">项目2</div> <!-- 这是Flex项目 -->
<div class="item">项目3</div> <!-- 这是Flex项目 -->
</div>
1 | .container { |
⚠️ 重要提醒:
只有直接子元素才是Flex项目!
如果.container里面有个<div>,<div>里面又有<p>,那么<p>不是Flex项目(因为不是直接子元素)。
3.2.2 主轴和交叉轴:Flex布局的"坐标系"
生活类比:
想象你在整理书架: - 主轴 =
书架的横向(从左到右,或从右到左) -
交叉轴 =
书架的纵向(从上到下,或从下到上)
Flex布局中的两个轴:
| 轴 | 默认方向 | 作用 | 类比 |
|---|---|---|---|
| 主轴(Main Axis) | 水平方向(从左到右) | 控制Flex项目的排列方向 | 书架的横向 |
| 交叉轴(Cross Axis) | 垂直方向(从上到下) | 控制Flex项目的对齐方式 | 书架的纵向 |
示意图: 1
2
3
4
5
6
7主轴(Main Axis)→→→→→→→→→→→→→
↑
↑
交叉轴
(Cross Axis)
↑
↑
💡 记忆技巧:
- 主轴 = 主要排列方向(横向或纵向)
- 交叉轴 = 垂直于主轴的方向
- 默认情况下,主轴是横向,交叉轴是纵向
3.3 Flex布局的常用属性(必须掌握)
3.3.1 容器的属性(在Flex容器上设置)
1. display: flex; -
开启Flex布局
作用:让元素变成Flex容器
语法: 1
2
3.container {
display: flex; /* 开启Flex布局 */
}
实际例子: 1
2
3
4
5<div class="box">
<div>项目1</div>
<div>项目2</div>
<div>项目3</div>
</div>
1 | .box { |
效果:三个<div>会横向排列(并排显示),而不是垂直排列。
2. flex-direction -
控制主轴方向
作用:决定Flex项目沿着哪个方向排列
可选值:
| 值 | 效果 | 主轴方向 |
|---|---|---|
row(默认) |
横向排列(从左到右) | 水平 |
row-reverse |
横向排列(从右到左) | 水平(反向) |
column |
纵向排列(从上到下) | 垂直 |
column-reverse |
纵向排列(从下到上) | 垂直(反向) |
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13.container {
display: flex;
flex-direction: row; /* 横向排列(默认值) */
/* 项目1 | 项目2 | 项目3 */
}
.container {
display: flex;
flex-direction: column; /* 纵向排列 */
/* 项目1
项目2
项目3 */
}
💡 生活类比:
flex-direction就像决定"书架是横着放还是竖着放": -row= 横着放(书从左到右排列) -column= 竖着放(书从上到下排列)
3. justify-content
- 主轴对齐方式
作用:控制Flex项目在主轴上的对齐方式(这是最常用的属性之一!)
可选值:
| 值 | 效果 | 示意图 |
|---|---|---|
flex-start(默认) |
从主轴起点开始排列 | [项目1][项目2][项目3] |
flex-end |
从主轴终点开始排列 | [项目1][项目2][项目3] |
center |
在主轴上居中 | [项目1][项目2][项目3] |
space-between |
项目之间平均分布,首尾贴边 | [项目1] [项目2] [项目3] |
space-around |
项目周围平均分布 | [项目1] [项目2] [项目3] |
space-evenly |
项目之间完全平均分布 | [项目1] [项目2] [项目3] |
实际例子: 1
2
3
4.container {
display: flex;
justify-content: center; /* 项目在主轴上居中 */
}
效果对比: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/* 左对齐 */
justify-content: flex-start;
/* [项目1][项目2][项目3] */
/* 居中 */
justify-content: center;
/* [项目1][项目2][项目3] */
/* 右对齐 */
justify-content: flex-end;
/* [项目1][项目2][项目3] */
/* 平均分布(首尾贴边) */
justify-content: space-between;
/* [项目1] [项目2] [项目3] */
💡 记忆技巧:
justify-content= "主轴对齐"
想居中?用center!
想平均分布?用space-between!
4. align-items -
交叉轴对齐方式
作用:控制Flex项目在交叉轴上的对齐方式
可选值:
| 值 | 效果 | 说明 |
|---|---|---|
stretch(默认) |
拉伸填满容器 | 项目会被拉伸到容器高度 |
flex-start |
从交叉轴起点对齐 | 项目靠上对齐 |
flex-end |
从交叉轴终点对齐 | 项目靠下对齐 |
center |
在交叉轴上居中 | 最常用! 垂直居中 |
baseline |
基线对齐 | 文字基线对齐 |
实际例子: 1
2
3
4.container {
display: flex;
align-items: center; /* 项目在交叉轴上居中(垂直居中) */
}
效果对比(假设容器高度是100px): 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/* 靠上对齐 */
align-items: flex-start;
/* [项目1]
[项目2]
[项目3] */
/* 垂直居中 */
align-items: center;
/* [项目1]
[项目2]
[项目3] */
/* 靠下对齐 */
align-items: flex-end;
/* [项目1]
[项目2]
[项目3] */
💡 最常用场景:
想实现垂直居中?用align-items: center;!
这是Flex布局最强大的功能之一,以前需要写很多代码才能实现,现在一行搞定!
5. gap - 项目之间的间距
作用:设置Flex项目之间的间距(注意:这是较新的属性,现代浏览器都支持)
语法: 1
2
3
4.container {
display: flex;
gap: 20px; /* 项目之间间距20px */
}
实际例子: 1
2
3
4.container {
display: flex;
gap: 15px; /* 所有项目之间都有15px的间距 */
}
效果: 1
[项目1] --15px-- [项目2] --15px-- [项目3]
💡 为什么推荐用
gap?
以前设置间距需要用margin,但margin会有很多问题(比如首尾项目也会有外边距)。
gap属性专门用来设置项目间距,简单、直观、不会出错!
3.3.2 项目的属性(在Flex项目上设置)
flex -
控制项目的伸缩比例
作用:控制Flex项目如何分配剩余空间
语法: 1
2
3.item {
flex: 1; /* 平均分配剩余空间 */
}
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15.container {
display: flex;
}
.item1 {
flex: 1; /* 占1份 */
}
.item2 {
flex: 2; /* 占2份(是item1的2倍宽) */
}
.item3 {
flex: 1; /* 占1份 */
}
效果:item2的宽度是item1和item3的2倍。
💡 生活类比:
flex就像"分蛋糕": -flex: 1= 分1份 -flex: 2= 分2份(是1份的2倍) -flex: 3= 分3份(是1份的3倍)
3.4 实战案例:实现导航栏布局
3.4.1 需求分析
我们要做一个导航栏,包含: - 左侧:网站Logo - 右侧:导航链接(首页、关于、服务、联系)
布局要求: - Logo在左边,导航链接在右边 - 导航链接横向排列 - 所有内容垂直居中
3.4.2 HTML结构
1 | <header class="navbar"> |
3.4.3 CSS样式(完整代码)
1 | /* 导航栏容器:使用Flex布局 */ |
3.4.4 代码解析(逐步理解)
第一步:让导航栏变成Flex容器
1 | .navbar { |
效果:.navbar内的直接子元素(.logo和.nav-links)会变成Flex项目,横向排列。
第二步:让Logo和导航链接分布在两端
1 | .navbar { |
效果:Logo靠左,导航链接靠右,中间留空。
第三步:垂直居中
1 | .navbar { |
效果:Logo和导航链接在垂直方向上居中对齐。
第四步:让导航链接横向排列
1 | .nav-links { |
效果:所有链接横向排列,之间有20px的间距。
3.4.5 最终效果
1 | ┌─────────────────────────────────────────┐ |
- ✅ Logo在左边
- ✅ 导航链接在右边,横向排列
- ✅ 所有内容垂直居中
- ✅ 链接之间有间距
- ✅ 悬停时有交互效果
3.5 更多实战案例
案例1:卡片布局(三列等宽)
需求:三个卡片横向排列,等宽,间距相等
HTML: 1
2
3
4
5<div class="card-container">
<div class="card">卡片1</div>
<div class="card">卡片2</div>
<div class="card">卡片3</div>
</div>
CSS: 1
2
3
4
5
6
7
8
9
10
11.card-container {
display: flex;
gap: 20px; /* 卡片之间间距 */
}
.card {
flex: 1; /* 每个卡片平均分配空间(等宽) */
padding: 20px;
background-color: #f0f0f0;
border-radius: 8px;
}
效果:三个卡片等宽,横向排列,间距20px。
案例2:居中布局(最常用!)
需求:让一个元素在页面中完全居中(水平和垂直都居中)
HTML: 1
2
3<div class="center-container">
<div class="content">我要居中!</div>
</div>
CSS: 1
2
3
4
5
6
7
8
9
10
11.center-container {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
height: 100vh; /* 容器高度为视口高度 */
}
.content {
padding: 20px;
background-color: #f0f0f0;
}
效果:.content在页面中完全居中(水平和垂直都居中)。
🌟 这是Flex布局最强大的功能之一!
以前实现完全居中需要写很多代码,现在只需要3行CSS!
3.6 常见问题与解决方案
问题1:Flex项目没有横向排列?
可能原因: - 忘记写display: flex; -
Flex项目被其他CSS样式覆盖
解决方案: 1
2
3.container {
display: flex; /* 确保写了这一行 */
}
问题2:想实现垂直排列?
解决方案: 1
2
3
4.container {
display: flex;
flex-direction: column; /* 改为纵向排列 */
}
问题3:项目之间的间距怎么设置?
解决方案: 1
2
3
4.container {
display: flex;
gap: 20px; /* 使用gap属性(推荐) */
}
3.7 本节总结
你已经学会了:
✅ Flex布局的核心概念: - Flex容器和Flex项目 - 主轴和交叉轴
✅ 容器的常用属性: - display: flex; -
开启Flex布局 - flex-direction - 控制排列方向 -
justify-content - 主轴对齐(水平对齐) -
align-items - 交叉轴对齐(垂直对齐) - gap -
项目间距
✅ 项目的常用属性: - flex -
控制伸缩比例
✅ 实战技能: - 实现导航栏布局 - 实现卡片布局 - 实现居中布局
🌟 记住:
Flex布局是现代Web开发的必备技能!
掌握了Flex布局,你就能轻松实现90%的常见布局需求。
多练习,多实践,把Flex布局变成你的"肌肉记忆"!
4. 媒体查询应用:让网页"智能适配"
4.1 为什么需要媒体查询?
4.1.1 问题的出现:一个网页,多种设备
生活场景:
想象你设计了一件衣服: - 在模特身上很好看(桌面电脑) -
但给小朋友穿就太大了(手机) - 给高个子穿又太小了(平板)
网页的困境: - 在电脑上:三列布局,看起来很舒服 - 在手机上:三列挤在一起,字太小,根本看不清 - 在平板上:布局不协调,体验很差
传统解决方案(很麻烦): 1
2
3
4
5<!-- 方法1:为不同设备写不同的网页 -->
<!-- 电脑版:desktop.html -->
<!-- 手机版:mobile.html -->
<!-- 平板版:tablet.html -->
<!-- 问题:维护3个网站,成本太高! -->
💡 核心问题:
一个网页,需要在不同尺寸的屏幕上都能正常显示。
就像一件衣服,要能适应不同身材的人。
4.1.2 媒体查询的诞生(2012年)
2012年,CSS3正式引入媒体查询(Media Queries),让一个网页可以"智能适配"不同设备:
| 传统方式 | 媒体查询方式 |
|---|---|
| 为每个设备写一个网页 | 一个网页,自动适配 |
| 维护成本高 | 维护成本低 |
| 用户体验差 | 用户体验好 |
| 加载慢(需要判断设备) | 加载快(CSS自动判断) |
🌟 历史意义:
媒体查询让"响应式设计"成为可能,是现代Web开发的标准做法。
4.2 什么是媒体查询?
4.2.1 生活类比
媒体查询就像"智能空调": - 温度>30°C → 自动开启制冷 - 温度<20°C → 自动开启制热 - 温度20-30°C → 自动关闭
媒体查询: - 屏幕宽度>768px → 应用桌面样式(三列布局) - 屏幕宽度<768px → 应用手机样式(单列布局) - 屏幕宽度768-1024px → 应用平板样式(两列布局)
4.2.2 媒体查询的定义
媒体查询 = CSS的"条件判断"
根据设备的特性(屏幕宽度、高度、方向等),应用不同的CSS样式。
基本语法: 1
2
3@media (条件) {
/* 当条件满足时,应用这些样式 */
}
实际例子: 1
2
3
4
5
6
7
8
9
10
11/* 默认样式(所有设备) */
.container {
display: flex;
}
/* 当屏幕宽度小于768px时,应用这些样式 */
@media (max-width: 768px) {
.container {
flex-direction: column; /* 改为纵向排列 */
}
}
效果: - 屏幕宽度 >
768px:.container内的元素横向排列 - 屏幕宽度 ≤
768px:.container内的元素纵向排列
4.3 媒体查询的语法详解
4.3.1 基本语法结构
1 | @media [媒体类型] and (条件) { |
组成部分:
| 部分 | 说明 | 示例 |
|---|---|---|
@media |
媒体查询的关键字 | 必须写 |
媒体类型 |
设备类型(可选) | screen(屏幕)、print(打印) |
and |
逻辑运算符 | 连接多个条件 |
(条件) |
具体的判断条件 | max-width: 768px |
4.3.2 常用的媒体类型
| 媒体类型 | 说明 | 使用场景 |
|---|---|---|
screen |
屏幕设备(默认) | 电脑、手机、平板 |
print |
打印设备 | 打印网页时 |
all |
所有设备 | 不常用 |
实际例子: 1
2
3
4
5
6
7
8
9/* 屏幕设备 */
@media screen and (max-width: 768px) {
/* 样式 */
}
/* 打印设备 */
@media print {
/* 打印时的样式 */
}
💡 注意:
大多数情况下,我们只需要写@media (条件),不需要写screen,因为默认就是屏幕设备。
4.3.3 常用的媒体特性(条件)
| 媒体特性 | 说明 | 示例 |
|---|---|---|
max-width |
最大宽度(小于等于) | max-width: 768px(宽度≤768px) |
min-width |
最小宽度(大于等于) | min-width: 768px(宽度≥768px) |
max-height |
最大高度 | max-height: 600px |
min-height |
最小高度 | min-height: 600px |
orientation |
设备方向 | orientation: portrait(竖屏)orientation: landscape(横屏) |
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/* 当屏幕宽度小于等于768px时 */
@media (max-width: 768px) {
body {
font-size: 14px;
}
}
/* 当屏幕宽度大于等于1024px时 */
@media (min-width: 1024px) {
body {
font-size: 18px;
}
}
/* 当设备是竖屏时 */
@media (orientation: portrait) {
.sidebar {
display: none; /* 隐藏侧边栏 */
}
}
💡 记忆技巧:
-max-width: 768px= "宽度最多768px"(≤768px)
-min-width: 768px= "宽度至少768px"(≥768px)
4.4 响应式设计的断点(Breakpoint)
4.4.1 什么是断点?
生活类比:
断点就像"温度计上的刻度": - 0°C → 结冰 - 100°C → 沸腾
响应式设计的断点: - 768px → 手机和电脑的分界线 - 1024px → 平板和电脑的分界线
断点 = 根据屏幕宽度,改变页面布局的"临界点"
4.4.2 常用的断点值
| 设备类型 | 屏幕宽度 | 常用断点 |
|---|---|---|
| 手机 | < 768px | max-width: 768px |
| 平板 | 768px - 1024px | min-width: 768px 和 max-width: 1024px |
| 电脑 | > 1024px | min-width: 1024px |
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/* 手机样式(默认,移动优先) */
.container {
flex-direction: column; /* 单列布局 */
}
/* 平板样式(≥768px) */
@media (min-width: 768px) {
.container {
flex-direction: row; /* 两列布局 */
flex-wrap: wrap;
}
.item {
flex: 1 1 50%; /* 每个项目占50%宽度 */
}
}
/* 电脑样式(≥1024px) */
@media (min-width: 1024px) {
.item {
flex: 1 1 33.33%; /* 每个项目占33.33%宽度(三列) */
}
}
4.4.3 移动优先(Mobile First)策略
什么是移动优先?
传统方式(桌面优先): 1
2
3
4
5
6
7
8
9
10
11/* 先写桌面样式 */
.container {
display: flex; /* 三列布局 */
}
/* 再用媒体查询覆盖(手机) */
@media (max-width: 768px) {
.container {
flex-direction: column; /* 单列布局 */
}
}
移动优先方式(推荐): 1
2
3
4
5
6
7
8
9
10
11/* 先写手机样式(默认) */
.container {
flex-direction: column; /* 单列布局 */
}
/* 再用媒体查询增强(平板、电脑) */
@media (min-width: 768px) {
.container {
flex-direction: row; /* 横向布局 */
}
}
为什么推荐移动优先?
| 优势 | 说明 |
|---|---|
| 性能更好 | 手机用户先加载简单样式,加载更快 |
| 代码更简洁 | 从简单到复杂,逻辑更清晰 |
| 符合趋势 | 现在手机用户比电脑用户多 |
💡 记忆技巧:
移动优先 = "先写手机样式,再用媒体查询增强"
就像"先搭好基础框架,再逐步完善"
4.5 实战案例:制作自适应页面
4.5.1 需求分析
我们要做一个响应式卡片布局: - 手机(< 768px):单列布局,卡片占满宽度 - 平板(768px - 1024px):两列布局 - 电脑(> 1024px):三列布局
4.5.2 HTML结构
1 |
|
⚠️ 重要提醒:
必须在<head>中添加:这行代码告诉浏览器"按设备宽度显示",没有这行,媒体查询可能不生效!
1 <meta name="viewport" content="width=device-width, initial-scale=1.0">
4.5.3 CSS样式(完整代码)
1 | /* ===== 基础样式(手机,移动优先) ===== */ |
4.5.4 代码解析(逐步理解)
第一步:手机样式(默认)
1 | .container { |
效果:所有卡片垂直排列,每个卡片占满宽度。
第二步:平板样式(≥768px)
1 | @media (min-width: 768px) { |
效果:卡片横向排列,每行显示2个卡片。
第三步:电脑样式(≥1024px)
1 | @media (min-width: 1024px) { |
效果:每行显示3个卡片。
4.5.5 最终效果
手机(< 768px): 1
2
3
4
5
6
7
8
9┌─────────────┐
│ 卡片1 │
└─────────────┘
┌─────────────┐
│ 卡片2 │
└─────────────┘
┌─────────────┐
│ 卡片3 │
└─────────────┘
平板(768px - 1024px): 1
2
3
4
5
6┌──────────┐ ┌──────────┐
│ 卡片1 │ │ 卡片2 │
└──────────┘ └──────────┘
┌──────────┐ ┌──────────┐
│ 卡片3 │ │ 卡片4 │
└──────────┘ └──────────┘
电脑(> 1024px): 1
2
3
4
5
6┌────────┐ ┌────────┐ ┌────────┐
│ 卡片1 │ │ 卡片2 │ │ 卡片3 │
└────────┘ └────────┘ └────────┘
┌────────┐ ┌────────┐ ┌────────┐
│ 卡片4 │ │ 卡片5 │ │ 卡片6 │
└────────┘ └────────┘ └────────┘
4.6 更多实战案例
案例1:响应式导航栏
需求:电脑上显示横向导航,手机上显示汉堡菜单
HTML: 1
2
3
4
5
6
7
8
9
10<nav class="navbar">
<div class="logo">我的网站</div>
<ul class="nav-menu">
<li><a href="#">首页</a></li>
<li><a href="#">关于</a></li>
<li><a href="#">服务</a></li>
<li><a href="#">联系</a></li>
</ul>
<button class="menu-toggle">☰</button>
</nav>
CSS: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28/* 手机样式(默认) */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
}
.nav-menu {
display: none; /* 手机:隐藏菜单 */
}
.menu-toggle {
display: block; /* 手机:显示汉堡按钮 */
}
/* 电脑样式(≥768px) */
@media (min-width: 768px) {
.nav-menu {
display: flex; /* 电脑:显示菜单 */
gap: 20px;
list-style: none;
}
.menu-toggle {
display: none; /* 电脑:隐藏汉堡按钮 */
}
}
案例2:响应式字体大小
需求:根据屏幕宽度调整字体大小
CSS: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/* 手机:小字体 */
body {
font-size: 14px;
}
/* 平板:中等字体 */
@media (min-width: 768px) {
body {
font-size: 16px;
}
}
/* 电脑:大字体 */
@media (min-width: 1024px) {
body {
font-size: 18px;
}
}
4.7 常见问题与解决方案
问题1:媒体查询不生效?
可能原因: 1. 忘记添加viewport元标签 2.
媒体查询语法错误 3. CSS优先级问题
解决方案: 1
2<!-- 1. 确保HTML中有这行 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
1 | /* 2. 检查语法是否正确 */ |
问题2:断点值应该选多少?
推荐断点(根据主流设备): -
手机:max-width: 767px 或
max-width: 575px -
平板:min-width: 768px 和
max-width: 1023px -
电脑:min-width: 1024px
实际建议: - 不要设置太多断点(3-4个足够) - 根据实际内容调整,不要死记硬背 - 使用浏览器开发者工具测试(F12 → 设备工具栏)
问题3:移动优先还是桌面优先?
推荐:移动优先
原因: - 手机用户更多 - 性能更好(先加载简单样式) - 代码更简洁(从简单到复杂)
写法: 1
2
3
4
5
6
7
8
9
10
11/* 移动优先:先写手机样式 */
.container {
/* 手机样式 */
}
/* 再用媒体查询增强 */
@media (min-width: 768px) {
.container {
/* 平板/电脑样式 */
}
}
4.8 本节总结
你已经学会了:
✅ 媒体查询的核心概念: - 什么是媒体查询 - 为什么需要媒体查询
✅ 媒体查询的语法: - 基本语法结构 -
常用的媒体类型和特性 -
max-width和min-width的区别
✅ 响应式设计策略: - 断点的概念 - 移动优先策略 - 常用断点值
✅ 实战技能: - 制作自适应页面布局 - 响应式导航栏 - 响应式字体大小
🌟 记住:
媒体查询是实现响应式设计的核心工具!
掌握了媒体查询,你就能让网页在各种设备上都有良好的体验。
一个网页,适配所有设备,这就是现代Web开发的魅力!
5. AI实战:使用AI生成响应式布局
5.1 为什么用AI生成响应式布局?
5.1.1 响应式布局的复杂性
还记得我们刚才学的媒体查询吗?要实现一个完整的响应式布局,需要: - 写基础样式(手机) - 写平板样式(媒体查询) - 写电脑样式(媒体查询) - 测试不同设备 - 调试各种问题
工作量:一个简单的响应式页面,可能需要写100+行CSS代码。
5.1.2 AI的优势
AI可以帮你: - ✅ 快速生成完整的响应式布局代码 - ✅ 自动处理不同设备的适配 - ✅ 生成符合最佳实践的代码 - ✅ 节省大量时间
你的工作: - ✅ 描述需求(写Prompt) - ✅ 测试效果 - ✅ 微调细节
💡 生活类比:
以前:自己画设计图 → 自己写代码 → 自己调试(3天)
现在:告诉AI需求 → AI生成代码 → 你测试调整(3小时)
5.2 实战案例:用AI生成响应式导航栏
5.2.1 第一步:设计Prompt
目标:生成一个响应式导航栏
Prompt示例: 1
2
3
4
5
6
7用HTML和CSS创建一个响应式导航栏,要求:
1. 包含Logo(左侧)和导航链接(右侧)
2. 电脑上:横向显示所有链接
3. 手机上:显示汉堡菜单按钮,点击后展开菜单
4. 使用Flex布局和媒体查询
5. 样式现代化,有悬停效果
6. 代码注释清晰
5.2.2 AI生成的代码(示例)
HTML: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应式导航栏</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<nav class="navbar">
<div class="logo">我的网站</div>
<ul class="nav-menu" id="navMenu">
<li><a href="#">首页</a></li>
<li><a href="#">关于</a></li>
<li><a href="#">服务</a></li>
<li><a href="#">联系</a></li>
</ul>
<button class="menu-toggle" id="menuToggle">☰</button>
</nav>
</body>
</html>
CSS: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69/* ===== 基础样式 ===== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 30px;
background-color: #333;
}
.logo {
color: white;
font-size: 24px;
font-weight: bold;
}
.nav-menu {
display: flex;
list-style: none;
gap: 30px;
}
.nav-menu a {
color: white;
text-decoration: none;
padding: 8px 16px;
border-radius: 4px;
transition: background-color 0.3s;
}
.nav-menu a:hover {
background-color: #555;
}
.menu-toggle {
display: none; /* 电脑上隐藏 */
background: none;
border: none;
color: white;
font-size: 24px;
cursor: pointer;
}
/* ===== 手机样式(≤768px) ===== */
@media (max-width: 768px) {
.nav-menu {
position: fixed;
top: 60px;
left: -100%; /* 默认隐藏 */
width: 100%;
flex-direction: column;
background-color: #333;
padding: 20px;
transition: left 0.3s;
}
.nav-menu.active {
left: 0; /* 展开时显示 */
}
.menu-toggle {
display: block; /* 手机上显示 */
}
}
JavaScript(AI可能也会生成): 1
2
3
4// 切换菜单显示/隐藏
document.getElementById('menuToggle').addEventListener('click', function() {
document.getElementById('navMenu').classList.toggle('active');
});
5.2.3 测试和优化
测试步骤: 1. 在浏览器中打开页面 2. 按F12打开开发者工具 3. 点击"设备工具栏"图标(或按Ctrl+Shift+M) 4. 选择不同设备测试(iPhone、iPad、Desktop)
可能需要的优化: - 调整断点值 - 修改颜色和间距 - 优化动画效果
5.3 实战案例:用AI生成响应式卡片布局
5.3.1 Prompt设计
1 | 用HTML和CSS创建一个响应式卡片布局,要求: |
5.3.2 AI生成的代码(优化版)
HTML: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应式卡片布局</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="card">
<h3>卡片标题1</h3>
<p>这是卡片的内容描述...</p>
</div>
<div class="card">
<h3>卡片标题2</h3>
<p>这是卡片的内容描述...</p>
</div>
<div class="card">
<h3>卡片标题3</h3>
<p>这是卡片的内容描述...</p>
</div>
<div class="card">
<h3>卡片标题4</h3>
<p>这是卡片的内容描述...</p>
</div>
<div class="card">
<h3>卡片标题5</h3>
<p>这是卡片的内容描述...</p>
</div>
<div class="card">
<h3>卡片标题6</h3>
<p>这是卡片的内容描述...</p>
</div>
</div>
</body>
</html>
CSS: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57/* ===== 基础样式(手机,移动优先) ===== */
body {
margin: 0;
padding: 20px;
font-family: '微软雅黑', Arial, sans-serif;
background-color: #f5f5f5;
}
.container {
display: flex;
flex-direction: column; /* 手机:单列布局 */
gap: 20px;
max-width: 1200px;
margin: 0 auto;
}
.card {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.3s, box-shadow 0.3s;
}
.card:hover {
transform: translateY(-5px); /* 悬停时上移 */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.card h3 {
margin-top: 0;
color: #333;
}
.card p {
color: #666;
line-height: 1.6;
}
/* ===== 平板样式(≥768px) ===== */
@media (min-width: 768px) {
.container {
flex-direction: row; /* 改为横向排列 */
flex-wrap: wrap; /* 允许换行 */
}
.card {
flex: 1 1 calc(50% - 10px); /* 两列布局 */
}
}
/* ===== 电脑样式(≥1024px) ===== */
@media (min-width: 1024px) {
.card {
flex: 1 1 calc(33.33% - 14px); /* 三列布局 */
}
}
5.4 AI生成代码的优化技巧
5.4.1 如何写出更好的Prompt?
不好的Prompt: 1
写一个响应式布局
好的Prompt: 1
2
3
4
5
6
7用HTML和CSS创建一个响应式卡片布局,要求:
1. 使用Flex布局和移动优先策略
2. 手机(<768px):单列布局
3. 平板(768-1024px):两列布局
4. 电脑(>1024px):三列布局
5. 卡片有阴影、圆角、悬停效果
6. 代码注释清晰,使用语义化HTML标签
5.4.2 迭代优化:一步步完善
第一版Prompt:生成基础布局 1
创建一个响应式卡片布局
第二版Prompt:添加样式要求 1
2
3
4在刚才的基础上,添加:
- 卡片阴影效果
- 悬停动画
- 现代化配色
第三版Prompt:优化细节 1
调整间距和字体大小,让布局更协调
💡 技巧:
不要一次要求太多,分步骤让AI生成,更容易得到好结果。
5.4.3 检查AI生成的代码
必须检查的点: - ✅
是否添加了viewport元标签? - ✅ 媒体查询语法是否正确? - ✅
断点值是否合理? - ✅ 代码是否符合移动优先策略? - ✅
是否有明显的bug?
测试方法: 1. 在浏览器中打开 2. 用F12开发者工具测试不同设备 3. 检查是否有布局问题
5.5 常见问题与解决方案
问题1:AI生成的代码不工作?
可能原因: - 缺少viewport元标签 -
CSS文件路径错误 - 语法错误
解决方案: 1
2<!-- 确保有这行 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
1 | <!-- 检查CSS文件路径 --> |
问题2:AI生成的代码不符合需求?
解决方案: 1. 更详细地描述需求(写更具体的Prompt) 2. 分步骤生成(先基础布局,再添加样式) 3. 手动调整(AI生成的是起点,不是终点)
问题3:如何让AI生成更好的代码?
技巧: - ✅ 明确指定技术栈(Flex布局、媒体查询) - ✅ 说明设计风格(现代化、简洁) - ✅ 要求代码注释 - ✅ 指定断点值 - ✅ 要求移动优先策略
5.6 本节总结
你已经学会了:
✅ AI生成响应式布局的方法: - 如何设计有效的Prompt - 如何迭代优化代码 - 如何检查生成的代码
✅ 实战技能: - 用AI生成响应式导航栏 - 用AI生成响应式卡片布局 - 优化AI生成的代码
✅ 最佳实践: - 分步骤生成代码 - 详细描述需求 - 测试和优化
🌟 记住:
AI是强大的工具,但不能替代你的思考!
- AI生成代码 → 你测试和优化 → 最终产品
- 理解代码原理 → 才能用好AI工具
- 多练习 → 才能写出更好的PromptAI + 你的思考 = 高效开发!
6. 选讲:CSS变量与主题定制
6.1 为什么需要CSS变量?
6.1.1 传统方式的痛点
生活场景:
想象你在装修房子,选了一个主色调"蓝色": - 客厅用蓝色 - 卧室用蓝色 -
厨房用蓝色
问题来了:如果有一天你想改成"绿色",怎么办? - ❌ 传统方式:找到所有用蓝色的地方,一个一个改成绿色(100个地方要改100次!) - ✅ CSS变量方式:改一个变量的值,所有地方自动变成绿色(改1次,全部生效!)
传统CSS的问题: 1
2
3
4
5
6
7
8
9
10
11
12
13
14/* 传统方式:每个地方都要写具体的颜色值 */
.header {
background-color: #3498db; /* 蓝色 */
}
.button {
background-color: #3498db; /* 又是蓝色 */
}
.link {
color: #3498db; /* 还是蓝色 */
}
/* 想改成绿色?要改3个地方! */
💡 核心问题:
同样的颜色值(如#3498db)在代码中重复出现很多次,修改时需要在多个地方改,容易出错,维护困难。
6.1.2 CSS变量的诞生(2015年)
2015年,CSS3正式引入CSS变量(CSS Custom Properties),让样式管理变得简单:
| 传统方式 | CSS变量方式 |
|---|---|
| 重复写相同的值 | 定义一次,到处使用 |
| 修改要改很多地方 | 修改只需改1个地方 |
| 容易出错 | 不容易出错 |
| 代码冗长 | 代码简洁 |
🌟 历史意义:
CSS变量让样式管理从"手工作坊"变成了"现代化工厂",是CSS发展史上的重要进步。
6.2 什么是CSS变量?
6.2.1 生活类比
CSS变量就像"调色板": - 定义一次颜色(如"主色调 = 蓝色") - 在需要的地方引用("用主色调") - 想换颜色?改调色板上的定义就行
CSS变量: -
定义一次值(如--main-color: #3498db;) -
在需要的地方引用(color: var(--main-color);) -
想换颜色?改变量的定义就行
6.2.2 CSS变量的定义
CSS变量 = 可以重复使用的CSS值
基本语法: 1
2
3
4
5
6
7
8
9/* 定义变量 */
:root {
--变量名: 值;
}
/* 使用变量 */
选择器 {
属性: var(--变量名);
}
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/* 定义变量 */
:root {
--main-color: #3498db; /* 主色调:蓝色 */
--font-size: 16px; /* 字体大小 */
}
/* 使用变量 */
.header {
background-color: var(--main-color); /* 使用主色调 */
}
.button {
background-color: var(--main-color); /* 使用主色调 */
}
.text {
font-size: var(--font-size); /* 使用字体大小 */
}
效果: -
.header和.button都使用蓝色背景 -
.text使用16px字体大小 -
想改颜色?改--main-color的值就行!
6.3 CSS变量的语法详解
6.3.1 定义变量
语法:--变量名: 值;
规则: -
变量名必须以--开头(两个短横线) -
变量名区分大小写(--color和--Color是不同的变量)
- 值可以是任何CSS值(颜色、尺寸、字符串等)
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12:root {
/* 颜色变量 */
--primary-color: #3498db;
--secondary-color: #2ecc71;
/* 尺寸变量 */
--spacing: 20px;
--font-size-large: 24px;
/* 字符串变量 */
--font-family: '微软雅黑', Arial, sans-serif;
}
💡 命名建议:
使用有意义的变量名,如--main-color而不是--color1,这样代码更容易理解。
6.3.2 使用变量
语法:var(--变量名)
实际例子: 1
2
3
4
5.button {
background-color: var(--primary-color); /* 使用主色调 */
padding: var(--spacing); /* 使用间距 */
font-size: var(--font-size-large); /* 使用大字体 */
}
效果:.button的背景色、内边距、字体大小都使用变量中定义的值。
6.3.3 变量的作用域
生活类比:
变量的作用域就像"房间的规则": -
全局变量(:root)=
整个房子的规则(所有房间都遵守) -
局部变量(特定元素)=
某个房间的规则(只有这个房间遵守)
CSS变量的作用域:
| 定义位置 | 作用域 | 示例 |
|---|---|---|
:root |
全局(整个文档) | 所有元素都能使用 |
| 特定元素 | 局部(该元素及其子元素) | 只有该元素内部能使用 |
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/* 全局变量:所有元素都能用 */
:root {
--main-color: #3498db;
}
/* 局部变量:只有.container内部能用 */
.container {
--local-color: #e74c3c;
}
/* 使用全局变量 */
.header {
color: var(--main-color); /* ✅ 可以用 */
}
/* 使用局部变量 */
.container .item {
color: var(--local-color); /* ✅ 可以用(在.container内部) */
}
.other {
color: var(--local-color); /* ❌ 不能用(不在.container内部) */
}
6.3.4 变量的默认值
语法:var(--变量名, 默认值)
作用:如果变量未定义,使用默认值
实际例子: 1
2
3.text {
color: var(--text-color, #333); /* 如果--text-color未定义,使用#333 */
}
💡 使用场景:
当不确定变量是否已定义时,使用默认值可以避免样式失效。
6.4 实战案例:使用CSS变量实现主题切换
6.4.1 需求分析
我们要实现一个主题切换功能: - 默认:明亮模式(白色背景、黑色文字) - 切换后:暗黑模式(深色背景、浅色文字) - 点击按钮切换主题
6.4.2 HTML结构
1 |
|
6.4.3 CSS样式(完整代码)
1 | /* ===== 定义CSS变量(明亮模式,默认) ===== */ |
6.4.4 JavaScript代码(实现主题切换)
1 | // 获取切换按钮 |
6.4.5 代码解析(逐步理解)
第一步:定义变量(明亮模式)
1 | :root { |
效果:定义默认主题的变量。
第二步:定义变量(暗黑模式)
1 | [data-theme="dark"] { |
效果:当<html>元素有data-theme="dark"属性时,使用暗黑模式的变量值。
第三步:应用变量
1 | body { |
效果:body的背景色和文字颜色会根据当前主题自动变化。
第四步:JavaScript切换主题
1 | document.documentElement.setAttribute('data-theme', 'dark'); |
效果:给<html>元素添加data-theme="dark"属性,触发暗黑模式的CSS变量。
6.4.6 最终效果
明亮模式: - 白色背景 - 深色文字 - 浅色卡片
暗黑模式: - 深色背景 - 浅色文字 - 深色卡片
切换效果: - 点击按钮 → 主题立即切换 - 切换有平滑过渡动画 - 用户选择会保存到本地存储(下次打开页面时记住)
6.5 更多实战案例
案例1:多主题切换(不只是明亮/暗黑)
需求:支持明亮、暗黑、蓝色主题三种模式
CSS: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/* 明亮主题(默认) */
:root {
--bg-color: #ffffff;
--text-color: #333333;
--primary-color: #3498db;
}
/* 暗黑主题 */
[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #f0f0f0;
--primary-color: #4a9eff;
}
/* 蓝色主题 */
[data-theme="blue"] {
--bg-color: #e3f2fd;
--text-color: #1565c0;
--primary-color: #1976d2;
}
JavaScript: 1
2
3
4
5
6
7const themes = ['light', 'dark', 'blue'];
let currentIndex = 0;
themeToggle.addEventListener('click', function() {
currentIndex = (currentIndex + 1) % themes.length;
document.documentElement.setAttribute('data-theme', themes[currentIndex]);
});
案例2:响应式变量(根据屏幕大小改变值)
需求:不同屏幕大小使用不同的间距
CSS: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21:root {
--spacing: 10px; /* 默认间距 */
}
/* 平板:增大间距 */
@media (min-width: 768px) {
:root {
--spacing: 20px;
}
}
/* 电脑:更大间距 */
@media (min-width: 1024px) {
:root {
--spacing: 30px;
}
}
.container {
padding: var(--spacing); /* 自动适应不同屏幕 */
}
6.6 CSS变量的优势总结
| 优势 | 说明 | 实际效果 |
|---|---|---|
| 代码复用 | 定义一次,到处使用 | 减少重复代码 |
| 易于维护 | 修改只需改1个地方 | 改颜色只需改变量定义 |
| 动态切换 | 通过JavaScript动态改变 | 实现主题切换功能 |
| 作用域控制 | 全局或局部变量 | 灵活控制应用范围 |
| 类型安全 | 值可以是任何CSS类型 | 支持颜色、尺寸、字符串等 |
6.7 常见问题与解决方案
问题1:CSS变量不生效?
可能原因: 1.
变量名写错了(必须是--开头) 2.
作用域问题(变量定义的位置不对) 3. 浏览器不支持(IE不支持CSS变量)
解决方案: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/* 1. 检查变量名 */
:root {
--main-color: #3498db; /* ✅ 正确:--开头 */
main-color: #3498db; /* ❌ 错误:没有-- */
}
/* 2. 检查作用域 */
:root {
--color: #3498db; /* ✅ 全局变量,所有地方都能用 */
}
.container {
--color: #e74c3c; /* ✅ 局部变量,只有.container内部能用 */
}
/* 3. 提供回退值 */
.text {
color: var(--text-color, #333); /* 如果变量未定义,使用#333 */
}
问题2:如何在不支持CSS变量的浏览器中使用?
解决方案: 1
2
3
4
5/* 提供回退值 */
.button {
background-color: #3498db; /* 回退值(不支持CSS变量的浏览器用这个) */
background-color: var(--primary-color, #3498db); /* CSS变量(支持的浏览器用这个) */
}
💡 注意:
现代浏览器(Chrome、Firefox、Safari、Edge)都支持CSS变量。
只有IE浏览器不支持,但IE已经停止更新,可以忽略。
问题3:变量名应该怎么命名?
推荐命名方式: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/* ✅ 好的命名:语义化、清晰 */
:root {
--primary-color: #3498db; /* 主色调 */
--secondary-color: #2ecc71; /* 次要颜色 */
--spacing-small: 10px; /* 小间距 */
--spacing-large: 30px; /* 大间距 */
}
/* ❌ 不好的命名:不清晰 */
:root {
--color1: #3498db;
--color2: #2ecc71;
--size1: 10px;
--size2: 30px;
}
6.8 本节总结
你已经学会了:
✅ CSS变量的核心概念: - 什么是CSS变量 - 为什么需要CSS变量 - 变量的作用域
✅ CSS变量的语法: -
如何定义变量(:root、局部变量) -
如何使用变量(var()函数) - 变量的默认值
✅ 实战技能: - 使用CSS变量实现主题切换 - 多主题切换 - 响应式变量
✅ 最佳实践: - 变量命名规范 - 浏览器兼容性处理 - 代码组织方式
🌟 记住:
CSS变量是现代Web开发的重要工具!
掌握了CSS变量,你就能: - 让代码更简洁、易维护 - 实现动态主题切换 - 提升开发效率CSS变量 + JavaScript = 强大的主题定制能力!
本章总结
通过本章的学习,你已经掌握了:
✅ CSS基础: - CSS的作用和重要性 - CSS选择器的使用 - 选择器优先级
✅ Flex布局: - Flex容器和Flex项目 - 主轴和交叉轴 -
常用属性(justify-content、align-items等) -
实现导航栏布局
✅ 响应式设计: - 媒体查询的语法和应用 - 断点的概念 - 移动优先策略 - 制作自适应页面
✅ AI辅助开发: - 用AI生成响应式布局 - 优化AI生成的代码 - 写出更好的Prompt
✅ CSS变量(选讲): - CSS变量的定义和使用 - 实现主题切换功能
🌟 恭喜你!
你已经掌握了现代Web开发中CSS的核心技能!
这些知识将帮助你: - 制作美观的网页界面 - 实现响应式布局 - 提升开发效率继续练习,继续探索,Web开发的世界等着你! 🚀