主题
界面
主题
前端五节的第一站。后端学前端的深度标准:
不需要写出漂亮页面,但要能:① 看懂前端在做什么;② 联调时定位问题在前端还是后端;③ 在做 SSR/模板(《JSP 与 JSTL(技术演进理解)》)时写出结构正确的 HTML ✓
header / main / section / footer)★;| 后端场景 | 需要前端知识吗 |
|---|---|
| 联调时"页面显示不对" | ✅ 能判断问题在前端还是后端 ✓(最常见) |
| 写接口文档给前端 | ✅ 知道前端"怎么用"你的接口 ✓ |
| SSR / 模板(《JSP 与 JSTL(技术演进理解)》) | ✅ 直接写 HTML ✓ |
| 排查"CSS 把按钮盖住了" | ⚠️ 基础即可 |
| 层 | 语言 | 职责 | 类比 |
|---|---|---|---|
| 结构 | HTML | "页面上有什么" | 骨架 ✓ |
| 表现 | CSS | "长什么样" | 皮肤 ✓ |
| 行为 | JavaScript | "做什么"(《JavaScript 基础》) | 肌肉 ✓ |
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"> <!-- ★ 不写中文会乱码 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>订单管理</title>
</head>
<body>
<header><h1>订单管理</h1></header>
<main>
<section>
<table>…</table>
</section>
</main>
<footer>© 2026</footer>
</body>
</html>★ 语义化标签的价值(不是"必须用 div 也行"吗?):
| 价值 | 说明 |
|---|---|
| 可读性 | main 比"第三个 div"好懂 ✓ |
| 可访问性 | 屏幕阅读器依赖语义 ✓ |
| SEO | 搜索引擎理解页面结构(《JSP 与 JSTL(技术演进理解)》)✓ |
表单(后端最关心)★:
<form action="/api/orders" method="post">
<input name="productId" required>
<input name="quantity" type="number" min="1" max="100" required>
<button type="submit">提交</button>
</form>关键:name 属性决定"提交时参数叫什么" ★ ——联调时"参数对不上"先检查 name ✓
(前后端分离后:表单通常不再直接提交,而是 JS 用 fetch 发 JSON——但表单仍用于"收集输入" ✓)
三种引入:
<link rel="stylesheet" href="style.css"> <!-- ★ 外部(推荐)-->
<style> /* 内嵌 */ </style>
<div style="color:red"> <!-- 内联(尽量避免,[S3-021] 的 XSS 场景 ⚠️)-->常用选择器:
| 选择器 | 匹配 | 示例 |
|---|---|---|
.class | 类 | .btn ✓ |
#id | ID | #header |
tag | 标签 | table |
.a .b(后代) | a 里面的 b | .table .btn ★ |
:hover / :disabled | 伪类 | button:hover ✓ |
优先级(同一条规则谁赢):内联 > ID > 类 > 标签 ✓ ——这解释了"为什么我写的样式不生效"(被更高优先级覆盖了)✗
每个元素都是一个"盒子":
┌─────────── margin(外边距:与别的盒子的距离)───────┐
│ ┌──────── border(边框)───────────────────────┐ │
│ │ ┌───── padding(内边距:边框到内容的距离)─┐ │ │
│ │ │ content(内容:width/height) │ │ │
│ │ └────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘★ 最重要的一个设置:
* { box-sizing: border-box; }box-sizing | width: 100px 指 |
|---|---|
content-box(默认) | 只有内容 100px(加 padding 后实际更宽)✗ |
border-box ★ | 边框以内的总宽 100px(直观 ✓) |
这就是"为什么我的宽度对不上"的答案 ✓
一句话:把容器变成"弹性布局",子元素自动排列 ✓
.row {
display: flex;
justify-content: space-between; /* 主轴:两端对齐 */
align-items: center; /* 交叉轴:垂直居中 ★ */
gap: 12px; /* 子元素间距(比 margin 干净)✓ */
}常见布局的 Flexbox 写法:
| 需求 | 写法 |
|---|---|
| 水平垂直居中 ★ | display:flex; justify-content:center; align-items:center; |
| 左右分布(两端) | justify-content: space-between ✓ |
| 顶部导航横排 | display:flex; gap:16px ✓ |
| 子元素等分 | 子元素 flex: 1 ✓ |
★ 历史提醒:在 Flexbox 之前,"垂直居中"是个著名的难题 ✗ ——现在一行搞定 ✓(别再背老的居中技巧 ✓)
/* 手机上:表格横向滚动而不是挤压 */
.table-wrap { overflow-x: auto; }
/* 窄屏时隐藏侧栏 */
@media (max-width: 768px) {
.sidebar { display: none; }
}@media 查询:按屏幕宽度切换样式 ✓ ——知道有这回事即可(深入是前端的事)✓
<h1>订单管理</h1>
<table>
<tr><th>订单号</th><th>金额</th></tr>
<tr><td>ORD-1</td><td>398.00</td></tr>
</table><style>
body { font-family: sans-serif; margin: 24px; }
.toolbar { display: flex; gap: 8px; margin-bottom: 16px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background: #f5f5f5; }
tr:hover { background: #fafafa; } <!-- 行悬停高亮 ✓ -->
</style>
<main>
<div class="toolbar">
<input placeholder="搜索订单号">
<button>查询</button>
</div>
<table>
<thead><tr><th>订单号</th><th>状态</th><th>金额(元)</th></tr></thead>
<tbody>
<tr><td>ORD-1</td><td>已支付</td><td>398.00</td></tr>
</tbody>
</table>
</main>注意它已经"可用":border-collapse、悬停高亮、清晰的表头 ✓
<div style="display:table-row"> <!-- ✗ 用 div 模拟表格 -->
<div style="display:table-cell">ORD-1</div>
</div>问题:失去了语义(《JSP 与 JSTL(技术演进理解)》)、可访问性差、样式难维护 ✗
修:表格就用 <table>(数据表格的语义本来就是它)✓
⚠️ HTML/CSS 难以在命令行实测——它的"运行环境"是浏览器 ✓ 调试手段:浏览器 DevTools(F12) ✓
| DevTools 功能 | 用途 |
|---|---|
| Elements ★ | 看结构、实时改样式(立即生效 ✓) |
| Console | 看 JS 报错、执行 JS ✓ |
| Network ★★ | 看每个请求的状态码/响应/耗时 ——联调第一工具 ✓✓ |
| 来源/断点 | 调试 JS ✓ |
★ 联调时的黄金动作:F12 → Network → 看那个失败的请求:
| 看什么 | 结论 |
|---|---|
| 红色(请求失败) | 网络层问题(服务没起、CORS、防火墙)✓ |
| 400/422 | 后端校验拒绝了(看响应体 details)✓ |
| 401/403 | 认证/授权问题(《参数校验与全局异常处理》)✓ |
| 200 但页面不对 | 前端渲染问题 ✓ |
这一张表能解决 80% 的"联调扯皮" ✓ ——先看 Network,再决定找谁 ✓
| # | 错误 | 说明 |
|---|---|---|
| 1 | 不写 <meta charset="UTF-8"> | 中文乱码 ✗ |
| 2 | 表单 input 忘写 name | 提交时后端收不到 ✗ |
| 3 | 样式不生效就 !important ✗✗ | 优先级战争 ✗——先查优先级与覆盖关系 ✓ |
| 4 | 用固定像素布局 ⚠️ | 不同屏幕下错乱 ✗ ——用 Flexbox/百分比 ✓ |
| 5 | 把 id 当类用(一个 id 出现多次) | id 必须唯一 ✓(用 class)✓ |
box-sizing:给一个固定宽度的盒子加 padding,对比两种 box-sizing ✓;name 提交一次,观察后端收到了什么(空 ✗)——再补上 name ✓。扩展任务:把 6.2 改造成"由 JS 渲染数据":<tbody id="rows"> 留空,用 JS fetch 后端接口后动态生成 <tr>——这就是 《Ajax 与前后端交互》 的内容 ✓
<div> 也可以完成所有布局,所以语义化标签没有意义。(对 / 错).editorconfig 管不了 CSS 的"居中"?——不对,这题改为:为什么"元素宽度 100px 却占了 120px"?<input name="user-name"> 提交后,后端收到的参数名是什么?padding(内边距)、border(边框)、margin(外边距)✓box-sizing: content-box——padding 也计入总宽 ✗;设 border-box 解决 ✓(5.4)user-name ✓——就是 name 属性的值(不是 id,也不是 label 文字)★display:flex;左 width:200px; overflow:auto;右 flex:1 ✓name 属性)★;box-sizing: border-box ★★;《Ajax 与前后端交互》:页面怎么在不刷新的情况下拿数据。