适用读者:会把样式"写出来"但总调不齐的人;带学员过前端基础的人。
前置:S14-B01(前端全景)、S02(浏览器渲染基础)。
覆盖旧文:4504(HTML/CSS 全册 22 万字符)、4431(HTML&CSS)、4505–4510(day01–day06 笔记)、4515–4519(移动 Web 五天)、4430(WEB 概述)→ 20 篇 / 约 40 万字符。
扩展点:E-S14-017(盒模型与box-sizing的三种口径)、E-S14-018(Flex 六属性决策表)、E-S14-019(移动端适配三条路线:viewport / rem / vw)。
下一篇:S14-J06 · JS、Tomcat/Servlet 与前端工程化。
1. 一句话结论
"样式写对了但页面不齐"几乎总是三个原因:盒模型算错宽度、Flex 主轴/交叉轴搞混、没有统一间距与字号刻度。这三件事解决,90% 的"丑"和"歪"就消失了。
出处:
A-4504–A-4510(HTML/CSS 与 day 笔记)、A-4515–A-4519(移动 Web)、A-4431。
2. 盒模型与 box-sizing(E-S14-017)
/* 默认:content-box —— width 只指内容区,padding/border 会额外撑大 */
.card { width: 300px; padding: 16px; border: 1px solid #eee; } /* 实际占 334px */
/* 推荐:全局统一 border-box */
*, *::before, *::after { box-sizing: border-box; }
| 口径 | width 包含 |
结果 | 适用 |
|---|---|---|---|
content-box(默认) |
只有内容 | 加 padding 就变宽 | 很少主动用 |
border-box |
内容 + padding + border | 宽度可预期 | 项目默认 |
outline / box-shadow |
不占布局 | 不撑开 | 焦点环、阴影 |
判据:先统一 border-box 再谈布局——不统一,后面每个宽度都要手工扣 padding。
块级宽度三条经验:
.block { width: 100%; max-width: 720px; margin-inline: auto; } /* 限宽居中 */
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; }
3. Flex 六属性决策表(E-S14-018)
.row {
display: flex;
flex-direction: row; /* 主轴方向:row | column */
justify-content: space-between; /* 主轴对齐 */
align-items: center; /* 交叉轴对齐 */
gap: 12px; /* 间距(优先于 margin) */
flex-wrap: wrap; /* 允许换行 */
}
.row > .item { flex: 1 1 240px; } /* grow shrink basis:最小 240px,可长可缩 */
| 属性 | 作用轴 | 常用值 | 坑 |
|---|---|---|---|
flex-direction |
定主轴 | row/column |
与 justify/align 的对应关系随之交换 |
justify-content |
主轴 | flex-start/center/space-between/space-around |
只有一个子元素时 space-between 无效 |
align-items |
交叉轴 | center/stretch/baseline |
stretch 会被子项固定高度覆盖 |
flex-wrap |
是否换行 | nowrap(默认)/wrap |
不换行时子项会被压缩到溢出 |
gap |
子项间距 | 任意长度 | 老 Safari 需前缀(现代浏览器已支持) |
flex(子项) |
伸缩 | 1 1 auto / 0 0 auto |
flex: 1 等价 1 1 0%,会忽略内容宽度 |
判据:"主轴/交叉轴"是 Flex 唯一需要背的概念——column 时 justify 管垂直、align 管水平,很多人卡在这。
Flex vs Grid 选型:
| 场景 | 用 |
|---|---|
| 一维排列(导航、按钮组、卡片内布局) | Flex |
| 二维网格(卡片列表、仪表盘) | Grid |
| 居中一个元素 | Flex(justify+align center)或 display:grid; place-items:center |
4. 移动端适配三条路线(E-S14-019)
| 路线 | 写法 | 优点 | 缺点 |
|---|---|---|---|
| viewport + 响应式单位 | <meta name="viewport" content="width=device-width, initial-scale=1"> + rem/clamp() |
现代主流、无 JS、可访问性好 | 需设计断点 |
| rem 缩放(旧方案) | 根字号按屏宽 fontSize = clientWidth/10 |
一套设计稿等比缩放 | 字号被整体缩放,可读性差 |
| vw 缩放 | width: 6.4vw 等 |
纯 CSS 无 JS | 极端屏宽下文字过小 |
推荐写法(现代):
:root { font-size: clamp(14px, 0.9rem + 0.2vw, 18px); } /* 字号随屏幕轻微变化 */
.container { width: min(100% - 32px, 720px); margin-inline: auto; }
@media (max-width: 640px) { .nav { display: none; } } /* 断点用内容决定,不抄设备尺寸 */
判据:断点按"内容开始挤"的位置设,不按 iPhone 型号设——设备会变,内容不会。
5. 常见布局故障速查
| 现象 | 根因 | 修法 |
|---|---|---|
| 子元素超出父容器 | 宽度 + padding 超 100%(content-box) |
统一 border-box |
margin 上下不生效 |
相邻块 margin 合并(collapse) |
用 padding 或 gap/建立 BFC |
height:100% 无效 |
父元素无确定高度 | 用 min-height:100dvh 或 Grid/Flex 拉伸 |
| 固定头部遮住内容 | position:fixed 脱离文档流 |
给内容加 padding-top 或 scroll-margin-top |
| 移动端横向滚动条 | 某元素超宽或 100vw 含滚动条 |
width:100% + overflow-x:hidden 慎用、查超宽元素 |
| 文字在 Flex 子项里溢出 | 子项 min-width:auto 撑住 |
min-width:0(或 overflow:hidden) |
6. 语义化 HTML 与可访问性底线
<header> <nav aria-label="主导航"> … </nav> </header>
<main> <article> <h1>…</h1> <section aria-labelledby="s1"> … </section> </article> </main>
<footer> … </footer>
| 底线 | 原因 |
|---|---|
一个页面一个 <h1>,标题层级不跳级 |
屏幕阅读器与 SEO |
图片有 alt(装饰图用 alt="") |
无障碍 |
表单控件配 <label for> |
点击区域与读屏 |
焦点可见(不 outline:none) |
键盘可用性 |
| 颜色对比度 ≥ 4.5:1(正文) | WCAG AA |
7. 反例:五种"看着对但不合规"的写法
| 写法 | 问题 |
|---|---|
用 <div onclick> 当按钮 |
键盘不可达、无角色语义 |
只靠 float 做布局 |
需清浮动,已过时 |
用 !important 覆盖一切 |
权重失控,维护崩溃 |
height: 100vh 在移动端 |
地址栏导致内容被裁(用 dvh) |
全局 *{margin:0;padding:0} 不设 box-sizing |
宽度仍会算错 |
8. 自测
content-box与border-box的宽度差在哪?- Flex 的
column下justify与align各管什么? - Flex 与 Grid 的选型判据?
- 移动端适配三条路线?断点该按什么设?
margin合并在什么情况下出现?怎么规避?
答案
- 前者 width 只含内容,后者含 padding+border。
justify管垂直(主轴),align管水平(交叉轴)。- 一维用 Flex,二维用 Grid。
- viewport+响应式单位 / rem 缩放 / vw;断点按内容开始挤压处。
- 相邻块级元素的外边距;用 padding、gap 或建立 BFC。
9. 下一篇
S14-J06 · JS、Tomcat/Servlet 与前端工程化 —— 从脚本到构建产物:模块化演进、打包与压缩、SPA 与后端的边界、以及"为什么本地跑得线上不跑"。
本篇属于系列《S14 · 前端与可视化》。旧文来源:A-4504–4510、A-4515–4519、A-4431、A-4430;扩展点 E-S14-017/018/019。