布局实验室 Layout Lab
本章目录 / 案例进度
  1. 需求
  2. 骨架
  3. 实现
  4. 响应式
  5. 精修

第 1 章 · 设计原则

把「好看」拆成可执行的规则

布局不是装饰。对齐、留白、层级、栅格这四件事,决定了读者先看到什么、按什么顺序读、在哪里停下来。本章开始我们接手一个真实任务:为个人博客「远山手记」设计首页 —— 先用四条原则把一堆内容整理成一份可读的版面。

4 个知识点 4 个可交互演示 约 25 分钟

案例启动:「远山手记」首页。这是一份纯技术博客,作者希望读者 30 秒内判断「这里有没有我要的东西」,并能顺畅地连续读下去。本章交付物:一份对齐、间距、层级都成体系的线框结构。后面四章会依次补上骨架、实现、响应式与精修。

1.1

对齐:让所有边缘落在同一条线上

人的视觉系统会自动寻找对齐线;找不到时,页面读起来就「毛糙」。对齐的第一目的不是好看,而是减少读者需要解释的边缘数量。

讲解

对齐在解决什么问题

一条对齐线,等于一次「这几个元素是一伙的」的暗示。当你把页头的标题、正文的段首、卡片的名字都放在同一条左边界上,读者不需要再逐个判断它们的从属关系 —— 这是把认知成本从读者身上拿走。反过来,边缘每多一条,阅读就多一分噪声

页面上通常有三类可以对齐的「线」,优先级从高到低:

  • 版心边界:内容区左右两侧的竖线,是最强、最容易被感知的一条。所有主要区块都应对齐到它。
  • 文本基线:不同字号的文字并排时,让它们「坐」在同一条基线(baseline)上,而不是几何中心。
  • 栅格列线:当页面复杂到版心边界不够用时,用栅格细分(见 1.4)。

三个常见决策

场景 推荐 理由
多行正文 左对齐 每行起点一致,回扫成本最低。中英混排时两端对齐会把英文单词间拉出空洞(「河」)。
短标题 / 按钮 可以居中 一两行的短文本,居中不会破坏回扫节奏,反而更能聚焦。
长段落 不要居中 每行起点都在变,眼睛找不到下一行的开头,读三行就累了。

一个可操作的检查方法:眯起眼睛看页面(或者把截图缩到 25%)。如果这时还能看出几条清晰的竖线,说明对齐成立;如果看到的是边界互相错开的「毛边」,就说明有元素没落到线上。

严格对齐的代价
所有东西都严格落在栅格上,版面会显得「板」、缺少节奏,因为意外感被抹掉了。
有意的越界
让一张大图出血到版心之外,可以制造呼吸感与重点。但越界必须是唯一的、故意的 —— 两处越界就变成了失控。

关键代码

博客卡片:三层对齐一次写清 css
/* 三层对齐:基线、版心、栅格 */
  .post-card {
    display: flex;
    align-items: baseline;      /* 不同字号的文字并排 → 基线对齐,视觉上才「坐得住」 */
    gap: 12px;                  /* 间距同样要成体系,别随手写 11px */
  }

  .post-card__title { font-size: 24px; }
  .post-card__date  { font-size: 13px; color: var(--muted); }

  .post-card__tag {
    margin-left: auto;          /* 用 auto margin 靠右,不必再套一层容器 */
    align-self: center;
  }

  .post-card__body {
    text-align: left;           /* 多行正文永远左对齐 */
    max-width: 68ch;            /* 顺手把行宽管住,理由见 2.1 */
    margin-inline: auto;        /* 注意是「容器居中」,不是「文字居中」 */
  }
  
  • align-items: baselinecenter 的差别,是这个演示里最容易看出来的部分 —— 打开演示切一下就知道。
  • margin-left: auto 是 Flex 里最省事的靠边手法:它吃掉所有剩余空间,因此天然响应容器宽度变化。
  • margin-inline 是逻辑属性,在从左到右与从右到左的语言里都能正确居中。

动态演示

远山手记

设计与前端随笔

Grid

对齐不是为了整齐,而是为了让读者不必解释你的版面:标题、标签、按钮都落在同一条线上,眼睛一次就能扫完。

Aa baseline
文本对齐
元素对齐(交叉轴)
辅助开关

实时输出:上面每一步操作对应的 CSS css

建议的尝试顺序:先关掉「启用对齐」看看边界错位的观感,再打开「列参考线」逐个把元素放回线上;最后把元素对齐从 center 切到 baseline,观察头像、标题、标签的相对位置变化。

1.2

留白:间距是信息结构的可见形式

留白不是「剩下的地方」,它是分组与层级的载体。判断一段留白是否合格,看的是比例关系,而不是绝对值。

讲解

接近性原则:距离即关系

格式塔心理学的接近性原则说:人会把彼此靠近的元素归为一组。这条规律给了留白一个可操作的判据 —— 组内间距必须小于组间间距。卡片内部的标题与摘要靠得近、卡片与卡片之间离得远,读者不用看分割线就知道「这几行是一张卡」。

一旦这个关系反转(组内比组间还大),版面立刻失去结构:读者会开始怀疑「这张卡到底包含哪几行」。这就是很多「内容都对、但看着乱」的页面真正的病因。

用刻度代替随手取值

不要每次需要间距时临时想一个数。做法是先定义一条间距刻度(例如 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64),所有间距都从刻度里取。这样做有三个好处:

  • 节奏感来自比例,而不是来自某个魔数;
  • 改一处刻度,全站同步,不需要逐页调;
  • 团队协作时有共同语言,review 时不必争论「16 还是 18」。

本站自己用的就是这条刻度(见 assets/css/tokens.css 里的 --s-1 … --s-9),并且全部间距都是它的倍数 —— 这正是「本站是自身所讲方法的示范」的一处具体体现。

留白不足
信息密度高、一屏能看到更多,但读者需要消耗更多注意力去分组,长文尤其吃力。
留白过度
呼吸感强、显得高级,但一屏信息太少,滚动成本上升;在工具型界面里会直接降低效率。
取舍依据
读得越「深」的场景(长文、详情页),留白越要足;扫得越「快」的场景(列表、后台表格),留白越要省。

关键代码

间距刻度 + 组内 < 组间 css
:root {
    /* 一条刻度,全站共用;倍数关系比数值本身更重要 */
    --space: 16px;
  }

  .post-list {
    display: grid;
    /* 组间:1.9 倍 —— 让「卡片之间」明显大于「卡片内部」 */
    gap: calc(var(--space) * 1.9);
  }

  .post-card {
    padding: var(--space);                 /* 卡片自己的呼吸空间 */
    display: grid;
    gap: var(--space);                     /* 组内:1 倍 */
  }

  /* 只在需要「更紧密」的地方,才用 calc 缩小一档 */
  .post-card__meta {
    display: flex;
    gap: calc(var(--space) * 0.5);          /* 日期与标签是同一组的细粒度信息 */
  }
  
  • gap 而不是 margingap 只作用在项目之间,不会在首尾多出空白,也就不必写 :last-child { margin: 0 } 这类补丁。
  • 倍数让关系可读:看到 1.91,立刻知道哪一层是「组间」。
  • 如果项目用了 clamp() 做流体间距,刻度依然成立 —— 只是把刻度本身变成流体值。

动态演示

圣杯布局为什么还在被使用

2026-09-1212 分钟

三栏 + 通栏头尾 + 正文优先加载,这套需求今天依然常见。

Flexbox 与 Grid:按维度选型

2026-09-086 分钟

一维用 Flex,二维用 Grid。判断标准只有一条。

预设
辅助开关

实时输出:上面每一步操作对应的 CSS css

把「组间 > 组内」关掉,你会看到同样的内容和同样的间距总量,但分组关系瞬间消失 —— 这是整章最值得盯住看的一秒。

1.3

视觉层次:告诉读者先看哪里

层级不是把重要的东西加粗放大,而是建立一套「顺序」。顺序清晰,读者三秒内就知道从哪儿读起。

讲解

可用的层级手段,按「副作用」从小到大

  • 位置:越靠上、越靠左(在从左到右的语言里)越先被看到。这是最便宜的手段。
  • 字号:最直接的「重要性声明」。但字号差距太小等于没做,差距太大则会压碎正文。
  • 字重:在字号不变的前提下制造对比,副作用最小。适合在紧凑的界面里区分主次。
  • 颜色与透明度:把次要信息「往后推」而不是把主要信息「往前拉」,整体更安静。
  • 留白:环绕的空白越多,元素越被强调。这是最容易被忽略、也最高级的手段。
  • 装饰:边框、底色、图标。最抢眼,也最容易过量 —— 通常放在最后用。

用比例尺,而不是逐个调字号

定义一条等比字号刻度--base × ratio^n。基准 16px、比例 1.25,就得到 16 / 20 / 25 / 31 这样一组天生的层级。它的好处是层级关系由「比例」保证 —— 你不可能做出「标题和副标题差 1px」这种模糊的层次。

比例的选择本身就是设计判断:1.2 左右稳重、信息密度高,适合工具型界面;1.33–1.5 戏剧性强,适合杂志式版面与落地页。比例越大,可用的级数越少 —— 1.5 的比例下,四级之后字号就已经超出合理范围。

常见错误:层级过多。一个页面里出现五、六种字号,读者反而无法排序。多数页面的层级只需要三级:标题 / 正文 / 注释。超过三级时,先怀疑是不是把「装饰」当成了「层级」。

关键代码

一套比例尺建立三级层次 css
:root {
    --base: 16px;
    --ratio: 1.25;                                    /* 比例本身就是设计决策 */

    --step-0: var(--base);                            /* 16px  正文 */
    --step-1: calc(var(--base) * 1.25);               /* 20px  副标题 */
    --step-2: calc(var(--base) * 1.5625);             /* 25px  标题 */
    --step--1: calc(var(--base) / 1.25);              /* 12.8px 注释 */
  }

  .post-title {
    font-size: var(--step-2);
    font-weight: 700;              /* 字重:副作用最小的强调手段 */
    line-height: 1.2;              /* 字号越大,行高反而要越小 */
    letter-spacing: -0.02em;       /* 大字号需要收紧字距,否则显得松散 */
  }

  .post-meta {
    font-size: var(--step--1);
    color: var(--muted);           /* 把次要信息往后推,而不是把主要信息往前拉 */
  }
  
  • 字号越大,需要的行高倍数越小、字距越紧 —— 这是排版里的一条反直觉规律,因为大字的「视觉体积」本来就大。
  • remcalc 表达刻度,而不是直接写 25px:前者保留了「它从哪来」的信息。
  • 本站的 --step-* 刻度用了 clamp()(见 tokens.css),于是层级在大屏上也保持同样的比例关系。

动态演示

精选

用栅格与留白,把首页安顿好

先把信息排序,再让版面承担顺序。

层次的本质是顺序,不是装饰。当标题、副标题、正文、注释之间的差距足够明确时,读者根本不需要「努力」就能知道从哪儿读起。

2026-09-12 · 12 min · Grid

辅助开关

实时输出:上面每一步操作对应的 CSS css

把比例一路调到 1.0:四个层级全部塌成同样大小,页面立刻变得「平」——这就是层级缺失的真实手感。

1.4

栅格:把版心切成可以复用的份数

栅格不是「限制」,而是一套共享的分割方案。它让不同区块在不知道彼此细节的情况下,依然对得上。

讲解

栅格由四样东西构成

  • 列(column):内容的容器。列数决定了可组合的版式数量。
  • 槽(gutter):列与列之间的固定空隙。它保证「任何两块内容之间都至少有这么宽」。
  • 外边距(margin):版心与屏幕边缘的距离。它决定版心的最大宽度。
  • 基线(baseline,可选):行高的整数倍垂直网格。跨列对齐容易,跨基线对齐难 —— 后者通常只在内容极其密集的出版物上才值得做。

为什么常见 12 列

12 可以被 2、3、4、6 整除。这意味着同一个栅格能同时表达「一半 / 三分之一 / 四分之一 / 六分之一」这些最常用的比例,因此 12 列成为事实标准。16 列(可同时表达 2/4/8)用在内容更细碎的站点,24 列常见于设计系统 —— 本质上都是为了「一次定义,多种组合」。

对博客首页这种结构来说,12 列绰绰有余:正文占 8 列、侧栏占 4 列,卡片一行三张各占 4 列。列数不是越多越好:列数越多,槽的总宽度占比越难控制,最后往往退化成「每块都占满,栅格名存实亡」。

CSS Grid 时代的栅格:过去栅格要靠 float + 百分比(并留下 clearfix 与四舍五入误差),今天一行 grid-template-columns: repeat(12, minmax(0, 1fr)) 就够了。minmax(0, 1fr) 里的那个 0 很重要 —— 它防止长单词或长代码把列撑破。

栅格的价值
一致性来自约束。有了共同的分割方案,跨页面的版式才可能是「一套」的,而不是每一页各自为政。
栅格的代价
强约束会让版式趋于雷同。成熟的做法是:结构严格对齐栅格,视觉重量(颜色、图幅、留白)允许越界。

关键代码

12 列栅格与跨列内容 css
.layout {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));  /* 12 列:能被 2/3/4/6 整除 */
    gap: 24px;                                          /* 槽宽 */
    max-width: 1180px;                                  /* 版心 */
    margin-inline: auto;
    padding-inline: 16px;                               /* 小屏时的外边距 */
  }

  .layout > .hero    { grid-column: span 12; }          /* 通栏 */
  .layout > .article { grid-column: span 8; }           /* 正文 8/12 */
  .layout > .aside   { grid-column: span 4; }           /* 侧栏 4/12 */
  .layout > .card    { grid-column: span 4; }           /* 一行三张 */
  
  • span Ngrid-column: 1 / 9 更适合栅格:你只需要声明「占几份」,起始位置交给自动放置。
  • 槽宽用 gap,因此每一块内容都自动获得两侧的呼吸空间,不必再给单块算 margin。
  • 栅格是「版心内部」的规则;版心本身的宽度与居中由 max-width + margin-inline: auto 负责,两者分工明确。

动态演示

通栏 · 精选文章
主内容 · 文章流
侧栏
卡片 A
卡片 B
卡片 C
辅助开关

实时输出:上面每一步操作对应的 CSS css

把列数从 12 调到 5:正文占 3、侧栏占 2、卡片一行只有一张 —— 你会直观看到「列数决定了可表达的比例」。再关掉栅格显示,检查内容边界是否仍然对得上。