HTML5语义化标签

🧠 什么是语义化?

HTML 标签不再只是 “盒子”,而是自带含义的 “说明书”!语义化标签让浏览器、屏幕阅读器、搜索引擎轻松理解页面结构。

举个栗子🌰:用 <nav> 装导航栏,比 <div class="nav"> 更直白,类似于鞋盒与一个普通盒子(贴了一个标签上面写着我是鞋盒)的区别

🏗️ 经典页面结构

1
2
3
4
5
6
7
8
9
10
11
<!-- 像搭积木一样构建页面 -->
<body>
<header>👑网站标题和搜索框等</header>
<nav>🗺️导航菜单</nav>
<main>
<article>📰独立文章</article>
<section>📦内容部分(章节 / 主题分区)</section>
</main>
<aside>🎁侧边栏(广告 / 推荐等 "小彩蛋")</aside>
<footer>🛎️版权信息 + 联系方式</footer>
</body>

✨ 使用语义化标签的好处如下

受益方 收获 案例
👩 用户可读性 屏幕阅读器精准导航,无障碍服务友好 盲人用户通过 <header> 快速定位页头,aria属性得到播报
🤖 机器可读性 搜索引擎好感度 +10086 Google 优先收录用 <article> 包裹的文章

🎁 补充一些语义化标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 图片画廊的完美拍档 -->
<figure>
<img src="cat.jpg" alt="一只优雅的橘猫">
<figcaption>🐱本喵在此宣布占领这个 div!</figcaption>
</figure>

<!-- 时间旅行者必备 -->
<time datetime="2025-02-26">今天</time>

<!-- 高亮重点像荧光笔 -->
<mark>这段文字自带聚光灯效果</mark>

<!-- 折叠部分 -->
<details>
<summary>点击查看神秘代码</summary>
<code>console.log("Hello Semantic World!")</code>
</details>

🔍 ARIA 属性:无障碍服务下的语义加强

用 ARIA 属性加强语义:

1
2
3
4
5
6
7
8
<!-- 告诉屏幕阅读器:"这是重点!" -->
<div role="banner">...</div>

<!-- 让图表与标题建立关联 -->
<section aria-labelledby="chart-title">
<h2 id="chart-title">年度猫咪撒娇频率统计</h2>
<canvas>...</canvas>
</section>

类似的无障碍ARIA相关属性还有一些这里不再赘述,核心理念就是如果需要提供较好的无障碍服务时,合理使用ARIA属性能够极大提升网站的友好性!

CSS3相关进阶点

✈️选择器类型

各类型选择器:

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
<!DOCTYPE html>
<html>
<head>
<style>
/* 基础选择器 */
div { border: 1px solid black; } /* 元素选择器 */
#main { background: #f0f0f0; } /* ID选择器 */
.content { padding: 10px; } /* 类选择器 */
* { box-sizing: border-box; } /* 通配符 */

/* 属性选择器 */
[data-type="special"] { color: red; } /* 属性值匹配 */
input[type="text"] { border: 2px solid blue; } /* 属性存在匹配 */

/* 伪类选择器 */
button:hover { background: gold; } /* 交互伪类 */
tr:nth-child(odd) { background: #eee; } /* 结构伪类,这里指奇数行 */
a:visited { color: purple; } /* 链接伪类 */

/* 伪元素 */
p::first-letter { font-size: 2em; } /* 首字母伪元素 */
.block::after { /* 内容生成 ,非常有意思,可以结合动画制作动态下划线效果*/
content: " ▶";
color: green;
}

/* 组合选择器 */
nav > ul { list-style: none; } /* 子选择器 */
h2 + p { margin-top: 0; } /* 相邻兄弟 */
section ~ div { padding-left: 20px; } /* 后续兄弟 */

/* 否定伪类 */
:not(.exclude) { font-family: Arial; }
</style>
</head>
<body>
<div id="main">
<section class="content">
<h2 data-type="special">标题</h2>
<p>段落文本<span class="exclude">排除内容</span></p>
<div class="block">区块元素</div>

<nav>
<ul>
<li>列表项1</li>
<li>列表项2</li>
</ul>
</nav>

<table>
<tr><td>奇数行</td></tr>
<tr><td>偶数行</td></tr>
<tr><td>奇数行</td></tr>
</table>

<input type="text" placeholder="输入框">
<button>悬停按钮</button>
<a href="#">已访问链接</a>
</section>

<div>后续兄弟元素</div>
</div>
</body>
</html>

附:选择器语法练习网站

🎶选择器优先级

优先级排序:从低到高分别为内联样式 (最高优先级属性:!important) > 元素 + ID > ID > 元素 + 类 > 类选择器 > 属性选择器 > 类选择器 > 元素选择器

示例:

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
<style>
/* 最低优先级 */
div { background: gray; } /* 元素选择器 */

/* 第6优先级 */
.wrapper { background: blue; } /* 类选择器 */

/* 第5优先级 */
[data-test] { background: cyan; } /* 属性选择器 */

/* 第4优先级 */
div.content { background: green; } /* 元素+类组合 */

/* 第3优先级 */
#special { background: yellow; } /* ID选择器 */

/* 第2优先级 */
div#special { background: orange; } /* 元素+ID组合 */

/* 第1优先级 */
div { background: red !important; } /* !important覆盖 */
</style>

<div class="wrapper content"
data-test="true"
id="special"
style="background: pink " >
<!-- 实际上内联样式优先级最高 -->
I Love CSS
</div>

🎨 Flex 布局

💡 Flex 是什么?

适合单行快速布局,如制作导航栏时对links的排布,多行情况下建议使用grid布局

✨ 基础结构

1
2
3
4
5
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>

🎯 属性解析

🌍 主轴(横向)

  • flex-direction: 决定主轴方向
    • row (默认):左 → 右
    • row-reverse:右 → 左
    • column:上 → 下
    • column-reverse:下 → 上

🌍 对齐(主轴对齐)

  • justify-content: 设置主轴对齐方式
    • center:居中
    • flex-start:左侧
    • flex-end:右侧
    • space-around:均匀分布
    • space-between:两端对齐

🌐 交叉轴(纵向)

  • align-items: 设置交叉轴对齐方式
    • center:居中
    • flex-start:顶部
    • flex-end:底部
    • stretch:拉伸

🌐 换行策略

  • flex-wrap: 控制换行行为
    • nowrap (默认):不换行
    • wrap:自动换行
    • wrap-reverse:反向换行

🌟 子元素属性

✨ 独立控制子元素

1
2
3
4
5
.item {
flex-grow: 1; /* 子元素扩展 */
flex-shrink: 0; /* 子元素收缩 */
flex-basis: auto; /* 子元素宽度基准 */
}

✨ 对齐单一子元素

1
2
3
.item {
align-self: center; /* 覆盖 align-items */
}

🏁 青蛙游戏学习Flex布局

Flexbox Froggy👉 flexboxfroggy.com

用游戏方式学习该布局! 😊

🎨 Grid 布局

💡 Grid 是什么?

适合复杂二维布局,如制作仪表盘、网页整体布局等,能够同时控制行和列,实现精确的页面结构设计。

✨ 基础结构

1
2
3
4
5
6
7
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
</div>

🎯 属性解析

🌍 容器属性

  • **display: grid;**:将容器设置为网格布局。

  • **grid-template-columns:**:定义列的大小和数量。

    • repeat(3, 1fr):创建三列,每列大小相等。(此处需要补充一个tricks:repeat(auto-fit/auto-fill,minmax(250px,1fr))可以实现非媒体查询的响应式布局)
    • 100px 200px auto:第一列宽 100px,第二列宽 200px,第三列自适应。
  • **grid-template-rows:**:定义行的大小和数量。

    • 类似,略
  • **grid-gap:**:设置网格间距。

    • 10px 20px:行间距 10px,列间距 20px。

    • **grid-template-areas:**:用于定义网格区域的命名区域。

    • 示例代码:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      /* 网格布局容器 - 3行3列结构 */
      .grid-container {
      display: grid;
      grid-template-areas:
      "header header header" /* 核心1:首行全宽 (区域分配) */
      "sidebar content content" /* 中间行:侧边栏 + 主内容区 */
      "footer footer footer"; /* 尾行全宽 */
      gap: 10px; /* 网格间隙 */
      }

      /* 头部区域 - 自动铺满第一行 */
      .header {
      grid-area: header; /* 核心2:对应模板首行区域 */
      background-color: #4CAF50;
      }

      /* 侧边栏区域 - 占据第二行首列 ,后续代码略*/

      • 在这个例子中,grid-template-areas 将网格分为四个区域:header、sidebar、content 和 footer。每个区域通过 grid-area 属性指定到对应的子元素。

🌐 项目属性

  • **grid-column:**:指定项目所在的列。
    • 1 / 3:项目跨越第 1 到第 3 列。
    • 1 / span 2:项目从 1 开始跨越两行。
  • **grid-row:**:指定项目所在的行。
    • 类似,略
  • **grid-area:**:指定项目所在的区域的布局。
    • header / sidebar / content / footer:定义项目在网格中的区域。

🏁 网格游戏学习 Grid 布局

Grid Garden 👉 Grid Garden - A game for learning CSS grid (cssgridgarden.com)

用游戏方式学习 Grid 布局! 😊

🧱 BEM 规范

BEM是Block(块)、Element(元素)、Modifier(修饰符)的缩写。它通过命名规则来提高代码的可读性和可维护性。

👀 BEM 的核心概念

  • Block(块):一个独立的模块,可以独立存在,不依赖其他模块。例如,一个导航栏、一个侧边栏、一个按钮等都可以被视为一个块。
  • Element(元素):依附于块的组成部分。一个块可以包含多个元素,元素无法脱离块独立存在。例如,按钮中的文字、按钮中的图标等都是按钮这个块的元素。
  • Modifier(修饰符):用于改变块或元素的外观、状态或行为的标记。例如,一个按钮可以有“禁用”状态、“选中”状态等,这些状态就可以通过修饰符来表示。

✨ BEM 的作用

  • 明确关系:通过命名规则可以清楚地看出元素之间的关系。例如,从类名“block__element_modifier”中可以看出这是一个块中的元素,且有一个修饰符。
  • 减少冲突:由于类名具有高度的可读性,可以避免类名重复和冲突。在大型项目中,多个开发人员同时开发不同的模块,BEM规范可以有效避免类名冲突的问题。
  • 便于维护:当需要修改或扩展某个块或元素的样式时,可以很容易地找到相关的类名,并进行修改。而且,由于类名具有明确的语义,其他开发人员也可以很快理解代码的结构和作用。

🔮 命名规则

类型 规则 示例
Block .block .button
Element .block__element .button__text
Modifier .block--modifier .button--disabled
Element + Modifier .block__element--modifier .button__text--large

🎨 示例代码

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
<!-- HTML -->
<div class="card">
<div class="card__header">Header</div>
<div class="card__body">
<p>This is the main content of the card.</p>
<button class="card__button card__button--primary">Primary Button</button>
</div>
<div class="card__footer">Footer</div>
</div>

<!-- CSS -->
.card {
border: 1px solid #ccc;
border-radius: 4px;
}

.card__header {
background-color: #f8f9fa;
padding: 10px;
}

.card__body {
padding: 20px;
}

.card__button {
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}

.card__button--primary {
background-color: #007bff;
color: #fff;
}

🌟 BEM 好处

  • 可读性:类名本身就是文档。例如,button--disabled 显然是禁用状态的按钮。
  • 可复用性:同样的块可以在多个地方复用。
  • 团队协作:统一的命名规范减少团队成员之间的沟通成本。

BEM犹如语义化的“身份证”,让代码更加直观、易于理解、便于协作。在大型项目中,遵循 BEM规范可以有效提高开发效率、降低维护成本。


📱 响应式断点与布局

响应式设计的核心目标是根据用户设备的屏幕尺寸动态调整网页布局,从而提升不同设备上的用户体验。

📏 实现响应式布局的常见方式

通过 CSS 的 @media 媒体查询,可以根据屏幕宽度设置不同的样式规则。以下是一个典型的示例:

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
@media screen and (max-width: 768px) {
/* 当屏幕宽度小于或等于 768px 时,应用以下样式 */
/* 768px 是常见的平板和手机屏幕分界线 */

body {
/* 调整网格布局结构 */
grid-template: minmax(100px, 1fr) minmax(100px, 1fr) 5fr / 4fr 1fr;
grid-template-areas: "header header" "nav nav" "main aside";
}

nav {
/* 导航栏从竖向布局切换为横向布局 */
flex-direction: row;
justify-content: space-between;
align-items: center;
}

.nav__item {
/* 圆形导航项样式 */
--radius: calc((100% - 10px * 4) / 5);
width: var(--radius);
aspect-ratio: 1;
border-radius: 50%;
}

.footer {
/* 在小屏幕上隐藏页脚 */
display: none;
}
}

🔄 不使用媒体查询的响应式布局

Grid响应式

除了 @media 查询,还可以通过 CSS Grid 的 repeat() 函数实现响应式布局。以下是一个动态调整卡片布局的示例:

1
2
3
4
5
.grid-container {
/* 使用 auto-fit 或 auto-fill 实现响应式布局 */
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
auto-fitauto-fill 的区别:
  1. **auto-fit**:
    • 当容器宽度足够时,列数会根据 minmax() 定义的最小/最大宽度自动调整。
    • 多余的空间会被均匀分配到每一列,确保容器填满。
  2. **auto-fill**:
    • 会尽可能多地填充列,若容器宽度仍有剩余,则会留出空白列。
    • 每一列的宽度会根据总列数均分,可能导致列宽较小。
🖥️ auto-fit对比auto-fill示例

以下是完整的 HTML 示例代码,展示了 auto-fillauto-fit 的对比效果。建议复制到浏览器中运行,拖拽调整宽度以直观体验两者的差异:

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>auto-fill vs auto-fit 对比演示</title>
<style>
/* 基础样式 */
body {
padding: 2rem;
font-family: Arial, sans-serif;
}

.demo-title {
color: #666;
margin: 1rem 0;
}

/* 容器公共样式 */
.grid-container {
border: 2px solid #999;
padding: 1rem;
margin: 1rem 0;
resize: horizontal; /* 允许横向拖拽调整宽度 */
overflow: auto;
min-width: 300px;
background: #f8f8f8;
}

/* 网格项样式 */
.item {
background: #2196F3;
color: white;
padding: 1rem;
border-radius: 4px;
text-align: center;
}

/* auto-fill 示例 */
#auto-fill-demo {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}

/* auto-fit 示例 */
#auto-fit-demo {
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

/* 网格公共设置 */
.grid-demo {
display: grid;
gap: 1rem;
margin: 1rem 0;
}

/* 控制按钮 */
.controls {
margin: 2rem 0;
display: flex;
gap: 1rem;
}
button {
padding: 0.5rem 1rem;
cursor: pointer;
}
</style>
</head>
<body>
<h2>请拖拽容器右侧边缘调整宽度 👉</h2>

<div class="controls">
<button onclick="addItem()">➕ 添加元素</button>
<button onclick="removeItem()">➖ 移除元素</button>
</div>

<!-- auto-fill 演示 -->
<h3 class="demo-title">auto-fill 模式(保留空白列)</h3>
<div class="grid-container">
<div class="grid-demo" id="auto-fill-demo">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
</div>

<!-- auto-fit 演示 -->
<h3 class="demo-title">auto-fit 模式(折叠空白列)</h3>
<div class="grid-container">
<div class="grid-demo" id="auto-fit-demo">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
</div>

<script>
// 动态添加/移除元素
let itemCount = 3;

function addItem() {
if(itemCount >= 8) return;
itemCount++;

const newItem = document.createElement('div');
newItem.className = 'item';
newItem.textContent = `Item ${itemCount}`;

document.querySelectorAll('.grid-demo').forEach(grid => {
grid.appendChild(newItem.cloneNode(true));
});
}

function removeItem() {
if(itemCount <= 1) return;
itemCount--;

document.querySelectorAll('.grid-demo').forEach(grid => {
grid.lastElementChild.remove();
});
}
</script>
</body>
</html>

🔄 容器响应式(Container Queries)

什么是容器查询?

容器查询是一种 CSS 特性,允许我们根据容器的尺寸(宽度或高度)来应用样式规则,而不是依赖媒体查询(@media)基于视口尺寸进行调整。容器查询的核心是 @container 规则。

示例
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>容器响应式示例</title>
<style>
/* 容器样式 */
.container {
container: test / inline-size; /* 核心,,定义响应式的容器名称和类型 */
width: 100%;
height: 100dvh; /* 100% 的视口高度 */
background-color: #fff;
padding: 20px;
box-sizing: border-box;
}

/* 文本内容样式 */
.text {
color: #000;
}

/* 容器查询:当容器宽度小于 2000px 时 */
@container test (width < 2000px) {
.text {
color: red; /* 文本颜色变为红色 */
}

.text::after {
content: "响应式触发了,宽度小于2000px"; /* 添加提示信息 */
display: block;
font-size: 0.9em;
color: #ff6b6b; /* 提示信息颜色 */
margin-top: 10px;
}
}

/* 注意:容器查询和媒体查询要放在最后,避免被覆盖 */
</style>
</head>
<body>
<div class="container">
<div class="text">
这是一个容器响应式示例。
</div>
</div>
</body>
</html>

预览

关键点说明
  1. container 属性
    • container: test / inline-size; 定义了一个名为 test 的容器查询,基于容器的宽度(inline-size)进行响应式调整。
    • inline-size 指的是容器的宽度(水平方向)。
  2. @container 查询
    • @container test (width < 2000px) 表示当容器的宽度小于 2000px 时,应用其中的样式规则。
    • 这与媒体查询(@media)类似,但作用范围是容器本身,而不是整个视口。

🎯 常用响应式案例

🍔 汉堡响应式

汉堡菜单是一种常见的移动端导航设计模式,当屏幕宽度缩小时,菜单栏会折叠成一个汉堡图标。以下是实现汉堡菜单的 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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>汉堡响应式菜单</title>
<style>
/* 默认大屏幕样式 */
.navbar {
display: flex;
background: #333;
padding: 10px;
}

.nav-links {
display: flex;
gap: 20px; /* 横向间距 */
list-style: none;
}

a {
color: white;
text-decoration: none;
}

.hamburger {
display: none; /* 大屏隐藏汉堡图标 */
color: white;
font-size: 1.5em;
cursor: pointer;
}

/* 移动端适配 */
@media (max-width: 768px) {
.hamburger {
display: block; /* 显示汉堡图标 */
}

.nav-links {
display: none; /* 默认隐藏菜单 */
position: absolute;
top: 50px;
width: 100%;
background: #333;
flex-direction: column; /* 纵向排列 */
}

/* 点击汉堡图标后显示菜单 */
#hamburger:checked ~ .nav-links {
display: flex;
}
}
</style>
</head>
<body>
<!-- 汉堡图标 + 隐藏的复选框(纯 CSS 方案) -->
<nav class="navbar">
<label for="hamburger" class="hamburger"></label>
<input type="checkbox" id="hamburger" hidden>

<!-- 导航菜单 -->
<ul class="nav-links">
<li><a href="#home">首页</a></li>
<li><a href="#about">关于</a></li>
<li><a href="#contact">联系</a></li>
</ul>
</nav>
</body>
</html>

🌊 瀑布流响应式

瀑布流布局是一种动态排列内容的方式,子元素会根据容器的列数均分并依次填充。以下是实现瀑布流布局的 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
70
71
72
73
74
75
76
77
78
79
80
81
<!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>
<style>
/* 基础重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

/* 瀑布流容器 */
.waterfall {
/* 核心 */
column-count: 3; /* 默认 3 列 */
column-gap: 20px; /* 列间距 */
padding: 20px;
}

/* 内容块样式 */
.item {
/* 核心 */
break-inside: avoid; /* 禁止内容断开 */
margin-bottom: 20px; /* 块间距 */
background: #fff;
border-radius: 8px;
padding: 15px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* 响应式适配 */
@media (max-width: 768px) {
.waterfall {
column-count: 2; /* 平板:2 列 */
}
}

@media (max-width: 480px) {
.waterfall {
column-count: 1; /* 手机:1 列 */
}
}
</style>
</head>
<body>
<div class="waterfall" id="waterfall"></div>

<script>
// 生成随机色块
function createItems() {
const container = document.getElementById('waterfall');
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEEAD', '#E8A798']; // 预定义色板

// 生成 30 个内容块
for (let i = 0; i < 30; i++) {
const item = document.createElement('div');
item.className = 'item';

// 随机高度(100px - 400px)
const height = Math.floor(Math.random() * 300 + 100);

// 随机颜色
const color = colors[Math.floor(Math.random() * colors.length)];

// 样式设置
item.style.height = `${height}px`;
item.style.backgroundColor = color;
item.innerHTML = `<span style="color: white;">内容块 #${i + 1}</span>`;

container.appendChild(item);
}
}

// 页面加载后生成
window.onload = createItems;
</script>
</body>
</html>

🎨 CSS 动画

CSS 动画是通过改变元素的样式属性来实现动态效果的技术。它可以通过 transition(过渡动画)、transform(变换)和关键帧动画(@keyframes)来实现。以下是详细讲解和实战案例。

🚀 1. transitiontransform

transition 管「动效怎么变」(过程),transform 管「变成啥样」(结果)。


极简对比表:

Transition Transform
功能 属性变化时的过渡动画 直接改变元素形态(旋转/缩放等)
触发条件 需要属性值变化(如悬停/JS修改) 立即生效
典型代码 transition: width 0.5s; transform: rotate(45deg);
性能 普通(CPU计算) 优化(GPU加速)

配合使用示例:

1
2
3
4
5
6
7
CSS.box {  
transform: scale(1); /* 初始状态,大小不变 */
transition: transform 0.3s ease; /* 监视的是transform状态,还可以监视width等,但性能差,动效过渡 */
}
.box:hover {
transform: scale(1.2); /* 最终状态,大小放大1.2倍 */
}

🔄 2. 关键帧动画 (@keyframes)

核心概念

@keyframes 是 CSS 中用于定义动画的关键帧规则。通过它,可以定义动画的起始状态、结束状态以及中间的过渡状态。

常用属性

  • animation-name:指定动画名称。
  • animation-duration:指定动画持续时间。
  • animation-timing-function:指定动画的速度曲线(如 linearease)。
  • animation-delay:指定动画延迟时间。
  • animation-iteration-count:指定动画的播放次数(如 infinite 表示无限循环)。
  • animation-fill-mode:指定动画结束时的状态(如 forwards 表示保持最后一帧的状态)。
  • animation-direction:播放方向(如 alternate 交替播放)。

示例:转圈加载动画

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>转圈加载动画</title>
<style>
/* 定义加载动画的样式 */
.loader {
width: 20px; /* 设置加载动画的宽度 */
height: 20px; /* 设置加载动画的高度 */
border: 4px solid rgba(0, 0, 0, 0.1); /* 设置边框样式,半透明黑色 */
border-top-color: #2196f3; /* 设置顶部边框颜色为蓝色 */
border-radius: 50%; /* 将元素设置为圆形 */
animation: spin 0.5s linear infinite; /* 应用旋转动画 */
}

/* 定义关键帧动画 */
@keyframes spin {
to {
transform: rotate(360deg); /* 旋转 360 度 */
}
}
</style>
</head>
<body>
<!-- 创建加载动画的容器 -->
<div class="loader"></div>
</body>
</html>

关键点说明

  1. @keyframes spin
    • 定义了一个从 0deg360deg 的旋转动画。
  2. animation 属性:
    • spin:动画名称。
    • 0.5s:动画持续时间为 0.5 秒。
    • linear:动画速度曲线为线性(匀速)。
    • infinite:动画无限循环。

🌟 动画属性详解

animation-fill-mode

  • 作用:定义动画结束后元素的状态。
  • 常见值
    • none:动画结束后,元素回到初始状态。
    • forwards:动画结束后,元素保持最后一帧的状态。
    • backwards:动画从头开始时,元素保持第一帧的状态。
    • both:结合 forwardsbackwards

animation-timing-function

  • 作用:定义动画的速度曲线。
  • 常见值
    • linear:匀速动画。
    • ease:先慢后快再慢。
    • ease-in:逐渐加速。
    • ease-out:逐渐减速。
    • ease-in-out:先加速后减速。
    • cubic-bezier(*n*,*n*,*n*,*n*):自定义动画曲线,具体可以查询网站✿ cubic-bezier

animation-duration

  • 作用:定义动画的持续时间。
  • 示例
    1
    animation-duration: 1s; /* 动画持续 1 秒 */

🚀 实战案例

1. 转圈加载动画

1
<div class="loader"></div>
1
2
3
4
5
6
7
8
9
10
11
12
.loader {
width: 20px;
height: 20px;
border: 4px solid rgba(0, 0, 0, 0.1);
border-top-color: #2196f3;
border-radius: 50%;
animation: spin 0.5s linear infinite;
}

@keyframes spin {
to { transform: rotate(360deg); }
}

2. 卡片悬停弹起效果

1
2
3
4
<div class="card">
<h3>悬停卡片</h3>
<p>鼠标悬停时卡片会弹起,实际是卡片上移加上阴影加深。</p>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.card {
background: white;
border-radius: 10px;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1);
overflow: hidden;
transform: translateY(0);/* 平移前 */
transition:
transform var(--transition-speed) ease,/* 平移过渡动画 */
box-shadow var(--transition-speed) ease;/* 阴影加深 */
}

.card:hover {
transform: translateY(-5px);/* 平移后 */
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}

3. 导航链接底线动画

效果预览:当鼠标悬停在导航链接上时,底部会出现一条平滑展开的下划线,增强交互反馈。

实现代码

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Navigation Link Underline Animation</title>
<style>
/* 导航整体样式 */
.nav {
display: flex;
gap: 2rem;
padding: 1rem;
background: #333;
}

/* 导航链接基础样式 */
.nav-link {
position: relative;
color: white;
text-decoration: none;
font-weight: bold;
transition: color 0.3s ease;
}

/* 导航链接悬停样式 */
.nav-link:hover {
color: var(--primary-color); /* 颜色变化提升交互感 */
}

/* 伪元素动画 */
.nav-link::after {
content: ''; /* 必需属性,用于生成伪元素 */
position: absolute; /* 绝对定位,相对于导航链接 */
bottom: 0; /* 底部对齐 */
left: 0; /* 左侧对齐 */
width: 0; /* 初始宽度为0 */
height: 2px; /* 线条高度 */
background: var(--primary-color); /* 线条颜色 */
transition: width 0.3s ease; /* 宽度过渡 */
}

/* 鼠标悬停时的动画效果 */
.nav-link:hover::after {
width: 100%; /* 宽度扩展至100%,形成完整下划线 */
}
</style>
</head>
<body>
<nav class="nav">
<a href="#" class="nav-link">首页</a>
<a href="#" class="nav-link">关于</a>
<a href="#" class="nav-link">服务</a>
<a href="#" class="nav-link">联系我们</a>
</nav>
</body>
</html>

关键代码解读

:hover::after 伪元素:通过伪元素实现下划线动画,避免额外的 HTML 标签。

🚀 游戏方式学习CSS动画

如果厌倦了枯燥的动画语法,可以在这个网站css-animations.io通过游戏的方式从零开始学习语法,快速提升!🫡

感想

HTML5+CSS3的内容到此就告一段落了,学习web前端不能急于求成,尤其是选择器,搞懂伪元素,动画,定位,布局(grid,flex)等等概念,对于后面的框架开发大有裨益,如果此文对你有帮助,我会十分开心!下次见!🫠