布局思路:从浮动到现代方案

早年的页面布局靠 float 加清除浮动,写起来繁琐、极易塌陷,还不得不掺入大量无语义的包装层。如今浏览器原生提供了两套布局模型:Flexbox 负责一维排布,Grid 负责二维网格。两者都是「声明容器与子项的相对关系」,由浏览器计算最终位置,不再需要靠魔法数字和负外边距去凑位置。

布局的难点从来不是「怎么让元素排成一行」,而是「当空间不够、内容变多、屏幕变窄时,它该怎么退化」——现代布局模型正是为后者设计的。
选择依据
  • 常规流文档默认排布,块级占满一行,行内元素随文字流动。
  • Flexbox一行或一列的排布:工具栏、导航、卡片内部对齐。
  • Grid行与列同时控制:页面骨架、卡片墙、仪表盘。
  • 共同点都基于容器与子项,用 gap 控制间距而非外边距。
HTML5 与 CSS3 现代布局配图:浏览器窗口内的模块化网格布局
网格线是布局的坐标系:先划分区域,再往里面放内容。

语义化 HTML:先把骨架立对

布局出问题,十次里有三次根源在 HTML 结构:该用 main 的地方堆了一排 div,列表项没有放进 ul,标题层级跳级。语义标签带来的好处很实际——屏幕阅读器能按区域跳转、浏览器能正确推断默认样式、搜索引擎能理解内容优先级,你写 CSS 时也少了一层「这层到底是不是多余」的判断成本。

<main class="page">
  <header class="hero">
    <h1>现代布局实战</h1>
    <p>用语义标签搭出可读的页面骨架</p>
  </header>
  <section class="card-grid" aria-label="文章列表">
    <article class="card">
      <h2>Flex 一维排布</h2>
      <p>适合工具栏与卡片内部对齐</p>
    </article>
  </section>
</main>

这段结构没有一行多余的包装层:main 表示页面主体,header 表示顶部区域,section 加 aria-label 说明这是一组文章,每张卡片用 article 独立成篇。CSS 只需要给这几个类写样式,选择器天然简洁。

Flexbox:一维排布的默认选择

Flex 的核心在于主轴与交叉轴的区分。flex-direction 决定主轴方向,justify-content 控制主轴上的分布,align-items 控制交叉轴对齐。flex 简写属性一次声明三个值:放大比例、收缩比例与基准尺寸,其中基准尺寸决定了收缩的起点,写 flex: 1 1 240px 的含义是「可涨可缩,但至少从 240 像素起步」。

.toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}
.toolbar .grow { flex: 1 1 240px; min-width: 0; }
.toolbar .btn  { flex: 0 0 auto; }
.toolbar .btn:focus-visible { outline: 2px solid #4A9DF2; }

这里有两个容易忽略的细节。min-width: 0 是让可伸缩项能够真正收缩到内容宽度以下——弹性项默认的最小尺寸是自动的,内部有长文本或图片时它会拒绝收缩,从而把布局撑破。flex-wrap: wrap 则保证窄屏时子项换行而不是被压扁。

Grid:二维布局的终局方案

当行与列都需要约束时,Grid 比 Flex 更直接。最有价值的一行写法是 grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)):它让浏览器自行决定放几列,每列不小于 260 像素,剩余空间平均分配。桌面端可能是四列,平板两列,手机一列,全程不需要写任何媒体查询。

写法列数来源适用场景
固定像素列手写尺寸完全可控的图表
auto-fit + minmax容器宽度卡片墙、商品列表
命名区域设计稿页面主骨架

整页骨架更适合用命名区域表达:grid-template-areas 用字符串画出布局草图,配合媒体查询在窄屏把侧栏挪到下方,改动只发生在字符串里,不必去调选择器的顺序与数值。

响应式断点与移动优先

移动优先的含义不是「先写手机的样式再补大屏」,而是「基础样式面向最窄的屏幕,用 min-width 逐级增强」。这样做的好处是样式表里只有正向追加,不会出现大段覆盖式改写;在只支持基础样式的老旧设备上,页面也仍然是可读的。

落地要点
  • 相对单位字号与间距用 rem、clamp(),随根字号与容器弹性变化。
  • 图片自适应img { max-width: 100%; height: auto },避免横向溢出。
  • 断点按内容定在内容开始变难看的地方断开,而不是照搬设备宽度。
  • 可访问字号不要用 user-scalable=no 禁止缩放,那会伤害低视力用户。