CSS Handbook · 布局

第六章 / 6.1 盒模型与定位

第六章 · 6.1 节

盒模型与定位


在深入 Flexbox 与 Grid 之前,必须先把地基打牢:每一个 HTML 元素在渲染时都会生成一个矩形的"盒子",理解这个盒子如何被测量、如何脱离或留在正常文档流中,是掌握一切布局技术的前提。

盒模型的四层结构

从内到外,一个盒子由内容区、内边距、边框、外边距四层同心矩形组成:

盒模型分层示意
margin 外边距
border 边框 / padding 内边距
content 内容区
相关属性说明
内容区width / height实际承载文字、图片等内容的区域
内边距padding内容与边框之间的留白,继承背景色
边框border环绕内边距的可见线条
外边距margin盒子与相邻盒子之间的间距,透明、不计入背景

box-sizing:两种计算方式

这是初学者最容易困惑的一点:设置了 width: 200px,为什么最终渲染出来的盒子比 200px 更宽?答案取决于 box-sizing

取值width/height 包含的范围
content-box(默认)仅内容区;最终渲染宽度 = width + padding + border
border-box内容区 + padding + border;width 就是最终渲染宽度
/* 几乎所有现代项目的第一行 CSS */
*, *::before, *::after {
  box-sizing: border-box;
}
为什么推荐 border-boxcontent-box 模式下,一旦调整 padding 或 border,元素的总宽度会跟着变化,破坏原本设计好的网格比例;border-box 让 width 所见即所得,是绝大多数现代 CSS 框架的默认选择。

display:外部与内部显示类型

display 同时控制两件事:这个盒子在"外部"如何参与父级的排列(外部显示类型),以及它的"内部"子元素如何排列(内部显示类型)。

取值外部类型特点
block块级独占一行,可设置 width/height
inline行内不换行,width/height 无效,只有水平方向 padding/margin 生效
inline-block行内不换行,但可设置 width/height 与垂直方向 padding/margin
none不生成盒子,从渲染树移除,不占据空间

display: flexdisplay: grid 则是把"内部显示类型"切换为弹性 / 网格排布,这正是 4.2 与 4.3 节的主题。

position 五种取值

取值是否脱离文档流定位基准
static(默认)正常文档流,偏移属性无效
relative相对自身原本的位置偏移,原位置仍占据空间
absolute相对最近的"已定位"祖先元素(见下)
fixed相对浏览器视口,滚动时不移动
sticky否(临界脱离)在阈值内正常流动,超出阈值后表现如 fixed
relative + absolute 组合示例
badge
父元素设为 relative,子元素的 absolute 就以它为基准定位。
.card { position: relative; }
.badge {
  position: absolute;
  top: 10px; right: 10px;
}

sticky 的常见用法

.section-title {
  position: sticky;
  top: 0;
  background: #f4f5f0;
}

本教程页面左侧的"本节目录"侧栏,就是用 position: sticky 实现的滚动跟随效果。sticky 元素必须有明确的 top(或 left/right/bottom)取值才会生效,且不能超出其父容器的可视范围。

偏移属性与包含块

absolute 元素究竟相对谁定位?规则是:沿 DOM 树向上查找,第一个 position 不为 static 的祖先元素,就是它的"包含块"(containing block)。如果一路找不到,就以整个文档(<html>)为基准。这也是为什么"父元素加 relative,子元素用 absolute 定位"是最常见的组合拳。

z-index 与层叠上下文

z-index 只在"层叠上下文"内部比较大小,且只对 position 不为 static 的元素(以及 flex/grid 子项)生效。多个层叠上下文之间互不干扰——子级里再大的 z-index,也无法超越父级层叠上下文之外的兄弟元素。

/* 会创建新的层叠上下文的常见属性 */
.modal {
  position: fixed;
  z-index: 1000;
}
/* opacity < 1、transform、filter 等同样会创建层叠上下文 */
排查技巧当 z-index "不生效"时,先检查元素是否已脱离 static 定位;再检查它的祖先链上是否存在某个更早创建的层叠上下文,把它"锁"在了较低的层级里。

小结

  • border-box 统一盒模型计算方式,让宽高所见即所得。
  • display 决定盒子对外的排列方式与对内的排布规则。
  • position 五种取值中,relative 常与 absolute 搭配,sticky 适合滚动跟随,fixed 适合全局悬浮元素。
  • z-index 只在同一层叠上下文内比较,排查层级问题要先定位"创建了层叠上下文"的祖先。