03 — CSS 基础回顾
你说你有 CSS 基础。本章不重复教 CSS,而是把项目里用到的、可能你没接触过的语法挑出来讲。
大约 10 分钟读完。
1. CSS 变量(自定义属性)— 项目核心
这是最重要的概念,项目所有颜色/间距/字体都用 CSS 变量统一管理。
1.1 定义与使用
1 2 3 4 5 6 7
| :root { --color-primary: #e8a548; --bg-surface: #141311; --space-4: 16px; --radius-md: 10px; }
|
1 2 3 4 5 6
| .button { background: var(--color-primary); padding: var(--space-4); border-radius: var(--radius-md); }
|
1.2 为什么要用变量?
1 2 3 4 5 6 7 8 9 10
| .a { color: #e8a548; } .b { border-color: #e8a548; } .c { background: #e8a548; }
:root { --color-primary: #e8a548; } .a { color: var(--color-primary); } .b { border-color: var(--color-primary); } .c { background: var(--color-primary); }
|
1.3 变量可以是颜色、字符串、甚至一整段样式
1 2 3 4 5 6
| :root { --color-primary: #e8a548; --bg-gradient: radial-gradient(ellipse at top, #1a1510 0%, #0c0b09 100%); --accent-line: linear-gradient(90deg, transparent, var(--color-primary), transparent); --shadow-glow: 0 0 20px rgba(232, 165, 72, 0.15); }
|
使用:
1 2 3 4
| .top { background: var(--accent-line); box-shadow: var(--shadow-glow); }
|
1.4 变量里再引用变量
1 2 3 4 5
| :root { --color-primary: #e8a548; --accent-line: linear-gradient(90deg, transparent, var(--color-primary), transparent); }
|
2. CSS Modules — *.module.css
文件命名规则:任何文件名包含 .module.css 的 CSS 文件,Vite 会把它当作 CSS Module 处理。
2.1 核心规则:类名会被「哈希」成唯一的
1 2 3 4 5 6 7 8
| .item { padding: 12px; }
.active { background: gold; }
|
1 2 3
| import styles from './ChatItem.module.css';
|
编译后的 HTML:
1
| <div class="ChatItem_item_a1b2c3 ChatItem_active_x7y8z9">
|
好处:不同组件的 .item 不会冲突。即使 Sidebar.module.css 里也有 .item,也完全是不同的类名。
2.2 项目里到处可见的模式
1 2 3 4 5 6 7 8
| <div className={`${styles.item} ${active ? styles.active : ''}`}>
<button className={`${styles.sendBtn} ${isSending ? styles.stop : ''} ${!canSend ? styles.disabled : ''}`} disabled={isSending ? false : !canSend} >
|
2.3 :global() — 让类名不被哈希
如果想在 CSS Module 里写「全局类名」(不被哈希):
1 2 3 4
| .markdown :global(.hljs) { background: transparent; }
|
:global() 里的 .hljs 保持原样,不被哈希。
这在覆盖第三方库样式时特别有用。
2.4 嵌套选择器
CSS Module 支持嵌套:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .item { padding: 12px; }
.item:hover { background: #201e1b; }
.item.active { color: white; }
.item .deleteBtn { opacity: 0; }
.item:hover .deleteBtn { opacity: 1; }
|
3. 单位与数值
3.1 rem vs px vs em
1 2 3
| font-size: 14px; font-size: 1rem; font-size: 1em;
|
项目里用 px 居多,rem 也有。本地不用太纠结,看到 1.5rem 就当作”稍大一号”。
3.2 颜色值多种写法
1 2 3 4 5
| color: #e8a548; color: #e8a5; color: rgb(232, 165, 72); color: rgba(232, 165, 72, 0.5); color: transparent;
|
3.3 calc() 计算
1 2
| width: calc(100% - 16px);
|
4. Flexbox(重点)
项目大量使用 flexbox。这是必备技能。
4.1 基本用法
1 2 3 4 5
| .container { display: flex; gap: 12px; padding: 16px; }
|
4.2 项目里的常见 flex 模式
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
| .center { display: flex; align-items: center; justify-content: center; }
.row { display: flex; gap: 12px; align-items: flex-start; } .avatar { width: 32px; height: 32px; } .content { flex: 1; }
.column { display: flex; flex-direction: column; gap: 8px; }
.space-between { display: flex; justify-content: space-between; align-items: center; }
|
1 2 3 4 5 6 7 8 9
| .list { flex: 1; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 4px; }
|
理解:
- 父级 sidebar 是
display: flex; flex-direction: column - 子级:header / list / footer
- list 用
flex: 1 占据中间所有可用高度 - list 内部再
display: flex; flex-direction: column 让 ChatItem 垂直堆叠
5. 媒体查询(响应式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .sidebar { width: 280px; }
@media (max-width: 767px) { .sidebar { position: fixed; left: 0; top: 0; bottom: 0; z-index: 60; transform: translateX(-100%); }
.sidebar.drawerOpen { transform: translateX(0); } }
|
@media 里写的样式只在满足条件时生效。本项目用 max-width: 767px 判断移动端。
6. 动画与过渡
6.1 transition — 过渡动画
1 2 3 4 5 6 7 8 9
| .button { background: gold; transition: all 250ms ease; }
.button:hover { background: orange; transform: scale(1.05); }
|
transition 的语法:transition: 属性名 时长 缓动函数
1 2
| transition: background 200ms ease; transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1);
|
6.2 @keyframes + animation — 关键帧动画
1 2 3 4 5 6 7 8 9 10
| @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.message { animation: fadeIn 300ms cubic-bezier(0.4, 0, 0.2, 1); }
|
项目里用到的动画:
| 名字 | 效果 | 用途 |
|---|
fadeIn | 淡入 + 上移 | 消息/对话框入场 |
slideUp | 滑入 + 缩放 | 确认弹窗 |
bounce | 弹跳 | AI 思考中的三点 |
pulse | 呼吸灯 | 工具调用进行中 |
spin | 旋转 | 加载图标 |
1 2 3 4
| transform: translateX(8px); transform: translateY(-2px); transform: scale(1.05); transform: rotate(360deg);
|
7. 一些常用 CSS 属性速查
7.1 边框与轮廓
1 2 3
| border: 1px solid rgba(255, 248, 240, 0.08); border-radius: 10px; outline: none;
|
7.2 阴影
1 2 3
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
box-shadow: 0 0 20px rgba(232, 165, 72, 0.15);
|
7.3 定位与层级
1 2 3 4
| position: relative; position: absolute; position: fixed; z-index: 100;
|
7.4 截断与省略号
1 2 3 4 5
| .title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
8. 本项目 CSS 系统的特点
| 特点 | 说明 |
|---|
| ✅ CSS 变量集中管理 | tokens.css 一处定义,全局使用 |
| ✅ CSS Modules | 每个组件样式独立,类名自动哈希 |
| ✅ Flex 布局为主 | 不使用 Grid、不使用 float |
| ✅ CSS 自定义动画 | 没用动画库,纯 CSS keyframes |
| ✅ 响应式最小化 | 仅 sidebar 有 @media,主内容自适应 |
| ❌ 不用 Sass/Less | 纯 CSS |
| ❌ 不用 Tailwind | 用 CSS Module + CSS 变量 |
接下来
现在你应该能读懂项目里大部分 CSS 了。
继续阅读 04-JavaScript基础回顾.md,了解 JavaScript 那些你可能不熟的语法。