Appearance
HTML 基础
浏览器打开页面时最先读取的是 HTML。HTML 不负责好看、不负责交互,它只管页面上有哪些内容、这些内容的结构是什么。CSS 管样式,JavaScript 管交互,HTML 负责搭出页面骨架。
HTML 文件本质是一份文本文件,扩展名 .html。浏览器读取后按标签(tag)生成一棵页面结构树,然后显示在屏幕上。
一、最小页面
新建文件 index.html,写一个能直接用浏览器打开的最小页面:
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>文章管理</title>
</head>
<body>
<h1>文章管理</h1>
<p>文章列表与发布记录。</p>
</body>
</html>双击这个文件,浏览器显示一个白底黑字的页面——大标题"文章管理",下面一行文字。朴素到没有任何样式,但结构已经在 了。
几个必须出现的标签:
| 标签 | 它是什么 | 不写会怎样 |
|---|---|---|
<!doctype html> | 告诉浏览器按 HTML5 标准解析 | 浏览器可能进入怪异模式,CSS 表现不一致 |
<html> | 整个页面的根 | 浏览器仍能渲染,但结构不规范 |
<head> | 元信息:编码、标题、样式引用 | 标题变成文件名,中文可能乱码 |
<meta charset="utf-8"> | 字符编码声明 | 中文大概率乱码 |
<title> | 浏览器标签页上的文字 | 标签页显示文件名或 URL |
<body> | 页面上能看见的所有内容 | 页面空白 |
head 和 body 容易混——凡是在页面上能看见的,放 body;凡是给浏览器和搜索引擎看的说明信息,放 head。
大多数标签成对出现,比如 <p>内容</p>。少数标签没有结束标签——<meta>、<link>、<img>、<input>——因为它们不包裹内容,只在自身位置生效。
二、文本结构
内容放进 <body> 后,用标题、段落、列表把层次分出来:
html
<h1>文章管理</h1>
<h2>已发布</h2>
<p>以下是近期发布的文章。</p>
<h2>草稿箱</h2>
<ul>
<li>Python 进阶语法整理</li>
<li>CSS 布局笔记</li>
<li>JavaScript 异步编程</li>
</ul>标题从 h1 到 h6,数字越大字越小。一个页面通常只有一个 h1,往下按层级用 h2、h3。HTML 里的标题标签表达的是内容层级关系(对屏幕阅读器和搜索引擎很重要),具体字号交给 CSS 控制。
常用文本标签:<p> 放段落、<ul> 配 <li> 放无序列表、<strong> 强调文本、<code> 放行内代码(文件名、状态值)、<pre> 保留换行和空格的多行文本(日志输出、配置片段)。
三、链接和资源
页面导航用 <a> 标签,href 决定跳转到哪里:
html
<nav>
<a href="articles.html">文章列表</a>
<a href="drafts.html">草稿箱</a>
<a href="#published">跳到已发布区域</a>
</nav>href 写法:相对路径(articles.html,跳同目录下另一个页面)、锚点(#published,跳到当前页面里 id="published" 的元素位置)、完整 URL(https://example.com,跳外部地址)。
图片用 <img>,没有结束标签,alt 写图片无法加载时的替代文本:
html
<img src="img/cover.png" alt="封面图">CSS 和 JavaScript 通过 <link> 和 <script> 引入:
html
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- 页面内容 -->
<script src="app.js"></script>
</body><link> 放 <head> 里(页面渲染前就要知道样式);<script> 放 <body> 末尾(等页面结构加载完再执行脚本——放 <head> 里的话,执行时页面元素还没出来,DOM 操作会找不到元素)。
四、表格
文章列表、分类统计这类行列数据,用表格展示:
html
<table>
<thead>
<tr>
<th>标题</th>
<th>分类</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr>
<td>Python 入门</td>
<td>技术</td>
<td>已发布</td>
</tr>
<tr>
<td>读书笔记</td>
<td>生活</td>
<td>草稿</td>
</tr>
</tbody>
</table><table> 是整个表格的容器,<thead> 是表头区域(列名那行),<tbody> 是数据区域,<tr> 是一行,<th> 是表头单元格(默认加粗居中),<td> 是普通数据单元格。
thead 和 tbody 可以省略,浏览器会自动补。但显式写出来有好处:后面用 CSS 分别控制表头和数据行样式更清楚;用 JavaScript 动态替换数据时只需要操作 tbody 的内容。
五、表单
页面不止看数据,还要能新增、编辑、筛选。表单用来收集用户输入——这是前端跟后端交互的入口,后面学到 fetch 和 FastAPI 时会频繁用到:
html
<form action="/api/articles" method="post">
<label for="title">标题</label>
<input id="title" name="title" type="text" required>
<label for="category">分类</label>
<select id="category" name="category">
<option value="tech">技术</option>
<option value="life">生活</option>
</select>
<button type="submit">提交</button>
</form>几个关键属性——不写的时候行为可能不符合预期:
| 属性 | 含义 | 不写会怎样 |
|---|---|---|
action | 表单数据提交到哪个地址 | 提交到当前页面地址,通常不是期望行为 |
method | get 拼在 URL 后面,post 放在请求体里 | 默认 get,数据暴露在地址栏 |
name | 字段提交时用的键名 | 这个字段不会被包含在提交数据里 |
for(label) | 对应哪个 id 的输入框 | 点击 label 文字不会聚焦输入框 |
type(input) | 输入框类型:text/password/number/url/email | 默认 text,没有类型校验 |
required | 浏览器提交前做必填检查 | 空值也能提交 |
常见输入类型:
html
<input type="text" name="title" placeholder="文章标题">
<input type="number" name="read_time" min="1" max="60" value="5">
<input type="checkbox" name="published" checked>
<input type="date" name="publish_date">
<textarea name="content" rows="5"></textarea><button> 的 type 要注意——表单里的按钮如果没明确指定 type,浏览器默认当提交按钮处理,点了就提交。普通操作按钮写 type="button":
html
<button type="button">预览</button>
<button type="submit">提交</button>六、语义标签
HTML5 提供了一批标签专门用来表达页面区域。它们外观跟 <div> 没区别,但名字本身表达了每个区域的职责:
html
<header>
<h1>文章管理</h1>
</header>
<nav>
<a href="#published">已发布</a>
<a href="#drafts">草稿箱</a>
</nav>
<main>
<section id="published">
<h2>已发布</h2>
<!-- 文章列表 -->
</section>
</main>
<footer>
<small>文章管理 v0.1</small>
</footer><header> 放页面顶部(标题、顶栏)、<nav> 放导航链接、<main> 放核心内容(一个页面只有一个)、<section> 放一个内容区块、<article> 放可以独立分发的内容(一篇文章详情)、<aside> 放辅助信息(侧栏统计)、<footer> 放页面底部。
不写语义标签全用 <div> 也能用,但浏览器开发者工具的 Elements 面板里全是 <div> 嵌套 <div>,排查结构时很难一眼看出每个区域是干什么的。
七、完整页面
把前面的标签合成一个静态页面骨架。现在没有任何样式和数据交互,只把结构搭对:
文件:index.html
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>文章管理</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>文章管理</h1>
<p>文章列表与发布记录。</p>
</header>
<nav aria-label="主导航">
<a href="#published">已发布</a>
<a href="#drafts">草稿箱</a>
</nav>
<main>
<section id="published">
<h2>已发布</h2>
<form action="/api/articles" method="post">
<label for="art-title">标题</label>
<input id="art-title" name="title" type="text" required>
<label for="art-category">分类</label>
<select id="art-category" name="category">
<option value="tech">技术</option>
<option value="life">生活</option>
</select>
<button type="submit">新增</button>
</form>
<table>
<thead>
<tr>
<th>标题</th>
<th>分类</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr>
<td>Python 入门</td>
<td>技术</td>
<td>已发布</td>
</tr>
<tr>
<td>CSS 布局笔记</td>
<td>技术</td>
<td>已发布</td>
</tr>
</tbody>
</table>
</section>
</main>
<footer>
<small>文章管理 v0.1</small>
</footer>
<script src="app.js"></script>
</body>
</html>打开这个页面会很朴素:白底黑字、没有间距、表格没有边框、表单字段挤在一起。HTML 只负责把内容和结构放清楚,样式和交互还没有进入页面——下一篇 CSS 解决"好不好看",再后面 JavaScript 解决"能不能交互"。
八、常见问题
| 现象 | 常见原因 | 检查入口 |
|---|---|---|
| 中文乱码 | 没写 <meta charset="utf-8"> 或文件实际编码不是 UTF-8 | 编辑器编码、浏览器页面编码 |
| 表单字段提交不上去 | 输入框缺少 name 属性 | 开发者工具 Network → Request Payload |
| 点击 label 文字没反应 | label for 和 input id 没对上 | Elements 面板 |
| 按钮点了页面刷新 | 表单里的 <button> 没写 type | 按钮属性 |
| 图片不显示 | src 路径相对于当前页面位置算错了 | Network 面板看请求路径 |
| 页面空白 | <body> 是空的、JavaScript 报错阻塞了渲染 | Console、Elements |
浏览器开发者工具按 F12 打开。Elements 面板看 HTML 结构,Console 看 JS 报错,Network 看资源和请求。HTML 阶段主要用 Elements:看标签是否按预期嵌套、属性是否写对。