Markdown 完全写作指南
Markdown 完全写作指南
Markdown 是一种轻量级标记语言,由 John Gruber 在 2004 年创建。它的核心设计理念是:用纯文本格式编写文档,同时保持易读性和可写性,最终可以轻松转换为结构化的 HTML。
本文将从基础到进阶,系统地展示 Markdown 的用法。
为什么选择 Markdown
在开始之前,先说说为什么 Markdown 值得花时间掌握:
- 纯文本,永不过时 — 不需要特定软件就能打开,几十年前的
.txt文件今天依然可读 - 专注于内容 — 写作时不会被排版干扰,思路更连贯
- 版本控制友好 — 纯文本让 Git diff 清晰可读,协作修改很方便
- 生态丰富 — 几乎所有静态站点生成器(Next.js、Hugo、Hexo、Jekyll)都支持 Markdown
- 转换灵活 — 可以导出为 HTML、PDF、Word、EPUB 等多种格式
作为一个程序员,Markdown 是我日常写作的默认格式。它让我把写文档和写代码的体验统一起来。
一、基础语法
1.1 标题
Markdown 使用 # 定义标题,# 的数量代表标题级别(1 到 6 级):
# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题
实际效果:
一级标题
二级标题
三级标题
四级标题
五级标题
六级标题
我个人习惯是:一篇文章只用一个一级标题(通常是文章标题本身),正文从二级标题开始。这样结构最清晰,也符合 HTML 语义。
1.2 段落与换行
Markdown 中,直接按回车不会换行。要开始新段落,需要空一行:
这是第一个段落。这段文字和下面那段之间
有一个空行,所以它们会被渲染成两个段落。
这是第二个段落。
实际效果:
这是第一个段落。这段文字和下面那段之间有一个空行,所以它们会被渲染成两个段落。
这是第二个段落。
1.3 强调文本
三种强调方式:
这是 **粗体文本**
这是 *斜体文本*
这是 ***粗斜体文本***
这是 ~~删除线文本~~
这是 `行内代码`
实际效果:
- 这是 粗体文本
- 这是 斜体文本
- 这是 粗斜体文本
- 这是
删除线文本 - 这是
行内代码
小技巧: 在中文和英文/数字之间手动加空格,阅读体验更好。比如「今天是 2026 年」比「今天是2026年」看起来更舒服。这不是 Markdown 语法,而是中文写作的排版习惯。
二、列表
2.1 无序列表
可以用 -、* 或 + 作为标记,推荐统一使用 -:
- 第一项
- 第二项
- 嵌套子项
- 另一个嵌套子项
- 第三项
实际效果:
- 第一项
- 第二项
- 嵌套子项
- 另一个嵌套子项
- 第三项
2.2 有序列表
数字加 .,Markdown 会自动编号——这意味着你写 1. 1. 1. 也会被渲染为 1. 2. 3.:
1. 安装依赖
2. 配置环境变量
3. 启动开发服务器
实际效果:
- 安装依赖
- 配置环境变量
- 启动开发服务器
2.3 任务列表
扩展语法(GitHub Flavored Markdown 支持):
- [x] 完成需求文档
- [x] 搭建项目框架
- [ ] 编写单元测试
- [ ] 部署到生产环境
实际效果:
- 完成需求文档
- 搭建项目框架
- 编写单元测试
- 部署到生产环境
2.4 混合列表
有序和无序可以混用,层级不受限制:
1. 前端开发
- React 组件
- 状态管理
- Zustand
- Jotai
2. 后端开发
- API 设计
- 数据库优化
三、代码块(高频使用)
这是程序员最常用的功能,也是 Markdown 的「杀手级特性」。
3.1 围栏代码块
使用三个反引号包裹,后面跟上语言标识符:
```typescript
// 一个简单的 TypeScript fetch 封装
interface FetchOptions extends RequestInit {
timeout?: number;
}
async function fetcher<T>(url: string, options: FetchOptions = {}): Promise<T> {
const { timeout = 8000, ...rest } = options;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
...rest,
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`HTTP ${"${"}response.status}: ${"${"}response.statusText}`);
}
return (await response.json()) as T;
} finally {
clearTimeout(timer);
}
}
// 使用示例
const data = await fetcher<{ title: string }>("/api/posts/hello");
console.log(data.title);
```
实际渲染:
// 一个简单的 TypeScript fetch 封装
interface FetchOptions extends RequestInit {
timeout?: number;
}
async function fetcher<T>(url: string, options: FetchOptions = {}): Promise<T> {
const { timeout = 8000, ...rest } = options;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
...rest,
signal: controller.signal,
});
if (!response.ok) {
throw new Error("HTTP ${"${"}response.status}: ${"${"}response.statusText}");
}
return (await response.json()) as T;
} finally {
clearTimeout(timer);
}
}
// 使用示例
const data = await fetcher<{ title: string }>("/api/posts/hello");
console.log(data.title);
3.2 更多语言的代码块
这个站点支持的语言高亮包括 javascript、typescript、python、bash、css、html、json、yaml、sql、markdown 等:
Python 数据处理示例:
import re
from collections import Counter
from pathlib import Path
def analyze_markdown(file_path: str) -> dict:
"""分析 Markdown 文件中的代码块语言分布"""
content = Path(file_path).read_text(encoding="utf-8")
matches = re.findall(r"```(\w+)", content)
return dict(Counter(matches))
result = analyze_markdown("example.md")
print(result)
# 输出示例: {"python": 3, "javascript": 2, "bash": 5}
SQL 数据库查询:
-- 查找最近 7 天最活跃的用户
SELECT
u.username,
COUNT(p.id) AS post_count
FROM
users u
INNER JOIN posts p ON u.id = p.author_id
WHERE
p.created_at >= CURRENT_DATE - INTERVAL "7 days"
AND p.status = "published"
GROUP BY
u.username
HAVING
COUNT(p.id) >= 3
ORDER BY
post_count DESC
LIMIT 10;
Shell 常用命令:
# 查找项目中所有 Markdown 文件,按修改时间排序
find . -name "*.md" -type f -printf "%T@ %p\n" | sort -rn | head -20
# 批量重命名 JPG -> jpg
for file in *.JPG; do
mv "$file" "${file%.JPG}.jpg"
done
# 统计 Git 仓库中各作者的提交数
git shortlog -sn --all
CSS 动画效果:
/* 入场动画 - 内容从下方淡入 */
@keyframes slide-up-fade {
from {
opacity: 0;
transform: translateY(24px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.markdown-content {
animation: slide-up-fade 0.4s ease-out both;
}
.markdown-content > *:nth-child(1) { animation-delay: 0s; }
.markdown-content > *:nth-child(2) { animation-delay: 0.05s; }
.markdown-content > *:nth-child(3) { animation-delay: 0.1s; }
JSON 配置文件:
{
"name": "chisssa-blog",
"version": "1.0.0",
"scripts": {
"dev": "next dev --turbo",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "15.0.0",
"react": "19.0.0",
"highlight.js": "^11.9.0"
}
}
YAML CI 配置:
name: Deploy Blog
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Vercel
run: npx vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
3.3 行内代码
用于在正文中提及变量名、函数名、文件路径:
在 `useEffect` 钩子中调用 `fetchPosts` 函数,配置文件在 `next.config.ts` 中修改。
实际效果:在 useEffect 钩子中调用 fetchPosts 函数,配置文件在 next.config.ts 中修改。
3.4 Diff 代码块(变更对比)
- import { useState } from "react";
+ import { useState, useEffect } from "react";
export default function PostPage() {
const [post, setPost] = useState(null);
+ const [loading, setLoading] = useState(true);
+ useEffect(() => {
+ fetchPost().then(setPost).finally(() => setLoading(false));
+ }, []);
}
四、链接与引用
4.1 行内链接
[GitHub](https://github.com)
[Next.js 官方文档](https://nextjs.org/docs)
[MDN Web 文档](https://developer.mozilla.org/zh-CN/)
实际效果:
4.2 参考式链接
当同一链接出现多次时,用参考式更整洁:
在 [GitHub][gh] 上托管代码,通过 [GitHub Actions][gh] 自动部署。
[gh]: https://github.com "GitHub 主页"
4.3 自动链接
用尖括号包裹 URL:
<https://www.markdownguide.org>
实际效果:https://www.markdownguide.org
4.4 常用学习资源
| 资源名称 | 链接 | 说明 |
|---|---|---|
| Markdown Guide | markdownguide.org | 最全面的 Markdown 入门教程 |
| GitHub Flavored Markdown | github.github.com/gfm/ | GitHub 的规范 |
| CommonMark | commonmark.org | 标准化规范 |
| Markdown 教程 | markdown.com.cn | 中文版教程 |
| Daring Fireball | daringfireball.net | 原始作者主页 |
五、表格
使用 | 和 - 创建表格:
| 工具 | 用途 | 推荐度 |
|------|------|--------|
| VS Code | 全能编辑器 | ⭐⭐⭐⭐⭐ |
| Obsidian | 知识管理 | ⭐⭐⭐⭐⭐ |
| Typora | Markdown 专用写作 | ⭐⭐⭐⭐ |
| Notion | 团队协作 | ⭐⭐⭐⭐ |
| iA Writer | 极简写作 | ⭐⭐⭐ |
实际效果:
| 工具 | 用途 | 推荐度 |
|---|---|---|
| VS Code | 全能编辑器 | ⭐⭐⭐⭐⭐ |
| Obsidian | 知识管理 | ⭐⭐⭐⭐⭐ |
| Typora | Markdown 专用写作 | ⭐⭐⭐⭐ |
| Notion | 团队协作 | ⭐⭐⭐⭐ |
| iA Writer | 极简写作 | ⭐⭐⭐ |
5.1 表格对齐
通过冒号控制对齐方向:
| 左对齐 | 居中对齐 | 右对齐 |
|:-------|:--------:|-------:|
| 文本 | 文本 | 123 |
| abc | abc | 45678 |
实际效果:
| 左对齐 | 居中对齐 | 右对齐 |
|---|---|---|
| 文本 | 文本 | 123 |
| abc | abc | 45678 |
5.2 API 接口表格示例
| HTTP 方法 | 路径 | 描述 | 认证要求 |
|-----------|------|------|----------|
| GET | `/api/posts` | 获取文章列表 | 否 |
| GET | `/api/posts/:slug` | 获取单篇文章 | 否 |
| POST | `/api/admin/save` | 创建/更新文章 | 是 |
| DELETE | `/api/admin/delete` | 删除文章 | 是 |
| GET | `/api/comments` | 获取评论 | 否 |
| POST | `/api/comments` | 发表评论 | 否 |
实际效果:
| HTTP 方法 | 路径 | 描述 | 认证要求 |
|---|---|---|---|
| GET | /api/posts |
获取文章列表 | 否 |
| GET | /api/posts/:slug |
获取单篇文章 | 否 |
| POST | /api/admin/save |
创建/更新文章 | 是 |
| DELETE | /api/admin/delete |
删除文章 | 是 |
| GET | /api/comments |
获取评论 | 否 |
| POST | /api/comments |
发表评论 | 否 |
六、引用块
6.1 基础引用
> 这是一段引用文字。引用可以包含**粗体**、*斜体*和`代码`等行内格式。
实际效果:
这是一段引用文字。引用可以包含粗体、斜体和
代码等行内格式。
6.2 嵌套引用
> 外层引用
>> 内层引用
>>> 更深一层
实际效果:
外层引用
内层引用
更深一层
6.3 技术文档中的引用
常见于 API 文档和 README:
注意: 在调用
savePost之前,确保已经通过auth()验证了用户身份,否则会收到401 Unauthorized错误。
提示: 本博客使用
remark和rehype处理 Markdown,配合highlight.js进行代码高亮。如果需要自定义渲染行为,可以参考 remark 官方文档。
警告: 不要在生产环境中使用默认的
NEXTAUTH_SECRET,请生成一个随机字符串替换它。
七、分割线
三个或更多的 -、* 或 _:
段落 A
---
段落 B
***
段落 C
实际效果:
段落 A
段落 B
段落 C
建议: 使用
---并在前后各空一行,这是最通用的写法。注意 frontmatter 也是用---包裹的,所以正文中不要误用。
八、图片
8.1 基础语法

替代文本在图片加载失败时显示,对无障碍访问很重要。
8.2 带链接的图片
[](https://picsum.photos)
8.3 图片尺寸控制
标准 Markdown 不支持设置图片尺寸,但可以用 HTML:
<img src="https://picsum.photos/800/300" alt="随机图片" width="600" />
实际效果(如果平台支持):
8.4 嵌入 YouTube 视频
如果博客支持 raw HTML 渲染,可以用 <iframe> 直接嵌入视频播放器:
<iframe width="100%" height="400"
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
frameborder="0" allowfullscreen>
</iframe>
实际效果:
必备前提: 此方法需要 Markdown 渲染器开启
allowDangerousHtml并安装rehype-raw插件,否则<iframe>会被丢弃。如果不支持 HTML,可以用下方第九章介绍的「封面图 + 链接」纯 Markdown 方式代替。
九、视频与媒体链接
Markdown 本身不支持直接嵌入视频播放器,但可以用链接配合封面图,做出「伪嵌入」的效果。
9.1 直接链接
最简单的方式——直接贴一个文本链接到视频平台:
[在 YouTube 上观看](https://www.youtube.com/watch?v=dQw4w9WgXcQ)
[在 B 站观看](https://www.bilibili.com/video/BV1GJ411x7h7)
9.2 带封面的视频链接(推荐)
用纯 Markdown 实现:把图片嵌套在链接中,点击缩略图即可跳转到视频平台,无需任何 HTML 或插件:
[](https://www.youtube.com/watch?v=视频ID)
实际效果:
这种方法不需要任何 HTML 代码或插件,纯 Markdown 就能做到「点击图片跳转视频」,在所有 Markdown 渲染器中都能正常工作。不依赖
rehype-raw,兼容性最好。
9.3 音频链接
同样的思路,用链接引导到外部音乐平台:
[在 Spotify 上收听](https://open.spotify.com/track/xxxxx)
音乐推荐:🎵 [Lofi Hip Hop Radio — YouTube](https://www.youtube.com/watch?v=jfKfPfyJRdk)
十、转义字符
当某个字符恰好也是 Markdown 语法标记时,用反斜杠 \ 转义:
\* 这不是斜体,而是星号本身
\# 这不是标题
\- 这不是列表项
\` 这不是行内代码
\> 这不是引用
\[ 这不是链接开始
可转义字符: \ * _ { } [ ] ( ) # + - . ! | ~
十一、Frontmatter
大多数静态站点生成器支持在 Markdown 文件开头使用 YAML frontmatter 来定义元数据:
---
title: "文章标题"
date: 2026-06-07
description: "文章摘要描述"
category: "分类名称"
tags:
- markdown
- 写作
- 教程
draft: false
---
# 正文从这里开始
这个博客目前支持的 frontmatter 字段:title、date、description、category。
十二、实际写作流程
我个人的写作流程如下:
- 在 VS Code 中新建
.md文件,填入 frontmatter - 用大纲确定结构(
Ctrl+Shift+O可以快速跳转标题) - 先写标题骨架,再填内容,避免写到一半迷失方向
- 按
Ctrl+Shift+V打开预览,边写边看渲染效果 - 提交到 Git,推到 GitHub,自动部署
推荐 VS Code 配置
在 VS Code 的 settings.json 中推荐以下设置:
{
"[markdown]": {
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 100,
"editor.quickSuggestions": false,
"editor.formatOnSave": true
},
"markdown.preview.breaks": true,
"markdown.preview.fontSize": 16
}
十三、扩展玩法
13.1 Mermaid 图表
部分平台(GitHub、Notion、Obsidian 等)支持用 Mermaid 语法绘制流程图和时序图。需要渲染器安装对应插件(如 mermaid):
```mermaid
graph TD
A[写 Markdown] --> B[Git Push]
B --> C[GitHub Action 触发]
C --> D[构建静态页面]
D --> E[部署到 CDN]
E --> F[用户访问]
```
本博客暂未安装 Mermaid 插件(mermaid 与 Edge Runtime 不兼容)。以上代码以原始形式展示。在 GitHub、Notion 等平台,它会渲染为真正的流程图 在客户端加载 Mermaid 组件渲染流程图。服务端仅输出原始代码块,浏览器接管后渲染为 SVG。,以上代码以原始形式展示。在支持 Mermaid 的平台(如 GitHub),它会渲染为一张流程图。如需在自己的博客中启用,需要安装
mermaid并用客户端动态 import 渲染。
13.2 数学公式(LaTeX)
部分解析器(Typora、Obsidian、Jupyter 等)支持 LaTeX 数学公式,需要 remark-math + rehype-katex 等插件:
行内公式:$e^{i\pi} + 1 = 0$
块级公式:
$$
f(x) = \int_{-\infty}^{\infty} \hat{f}(\xi) \, e^{2\pi i \xi x} \, d\xi
$$
本博客暂未安装 LaTeX 插件。以上显示的是原始 LaTeX 代码,在支持 LaTeX 的平台(Typora、Notion 等)它会渲染为真正的数学公式。需要在 unified 管线中安装
remark-math+rehype-katex并确认 Edge Runtime 兼容性 在服务端渲染 LaTeX 公式。由于rehype-katex在构建时会处理公式,可在 Edge Runtime 正常运行。如果你的博客也想支持,安装这两个包并引入 unified 管线即可。
13.3 表情符号(Emoji)
Markdown 中可以直接使用 Unicode 表情字符,它们是纯文本,无需插件就能显示:
🚀 部署成功 ✨ 新功能 📝 文档更新
💡 提示 ⚠️ 注意 ✅ 已完成
实际效果:
🚀 部署成功 ✨ 新功能 📝 文档更新
💡 提示 ⚠️ 注意 ✅ 已完成
部分平台(如 GitHub)还支持短代码写法
:rocket:→ :rocket:,但需要对应平台的支持,纯 Markdown 渲染器不解析它。直接用 Unicode 表情最通用。
十四、常见问题与踩坑记录
问题一:列表和代码块的缩进
代码块放在列表项中时,需要对反引号缩进:
1. 第一步:创建项目
```bash
npm create next-app@latest my-blog
```
2. 第二步:安装依赖
```bash
npm install remark remark-html
```
问题二:表格中的竖线
如果表格内容本身包含 |,需要用 \| 转义:
| 表达式 | 含义 |
|--------|------|
| `a \| b` | a 或 b |
| `[a-z]` | 小写字母范围 |
问题三:代码块中显示反引号
如果代码块内容本身包含三个反引号,外层用四个或更多反引号包裹:
````markdown
```typescript
const hello = "world";
```
````
问题四:Markdown 渲染器的差异
不同的 Markdown 解析器支持的特性不同:
| 特性 | CommonMark | GFM | 本博客 |
|---|---|---|---|
| 基础语法 | ✓ | ✓ | ✓ |
| 表格 | ✗ | ✓ | ✓ |
| 任务列表 | ✗ | ✓ | ✓ |
| 删除线 | ✗ | ✓ | ✓ |
| 脚注 | ✗ | ✗ | ✓ |
| Mermaid 图 | ✗ | ✗ | 可选 |
| 数学公式 | ✗ | ✗ | 可选 |
| HTML 混排 | ✓ | ✓ | ✓ |
十五、总结
Markdown 的核心优势在于它的「够用」——80% 的写作场景只需要 20% 的语法。掌握下面这个最小子集,就足以应对绝大多数日常写作:
| 场景 | 语法 |
|---|---|
| 标题 | ## ### |
| 强调 | **粗体** *斜体* |
| 列表 | - 1. |
| 链接 | [文字](URL) |
| 图片 |  |
| 代码 | `行内` 和 ```语言 |
| 引用 | > |
| 分割线 | --- |
| 表格 | ` |
记住: Markdown 的设计初衷是「易读易写」,不要为了炫技把文档搞得难以阅读。当 Markdown 语法不够用时,大胆使用 HTML——这是 John Gruber 在设计之初就允许的。
参考链接
- Markdown 官方指南(英文)
- CommonMark 规范
- GitHub Flavored Markdown Spec
- Markdown 教程(中文)
- VS Code Markdown 官方文档
- remark 生态
- highlight.js 文档
这篇文章本身就是一个 Markdown 语法示例。你可以查看源文件看到原始的 .md 文本。
