Skip to content

B33. 布局流 定位

3.1. ⭐ 默认布局流

浏览器的最大优势之一是打破了传统的固定宽高的布局,使布局流更加自由。程序员只需设置 CSS 属性,具体的位置计算交给浏览器便可。

块级与行内元素

css
/* 块级元素独占一行 */
div { display: block; }

/* 行内元素共存一行 */
span { display: inline; }

文档流特性:块级另起一行,连续的行级元素共用一行,存在空白折叠现象。

html
<!-- 默认布局演示 -->
<div>我会占据整行</div>
<span>我们</span>
<span>排在同一行</span>

3.2. 🌟 定位 position 属性

想让元素像便利贴一样"贴"在特定位置?定位属性就是你的布局瑞士军刀。

position 属性控制元素在文档流中的定位方式,分相对定位、绝对定位、固定定位、粘性定位。

3.2.1. 相对定位 relative

css
.relative {
  position: relative;
  top: 10px;  /* 向下移动10px */
  right: -20px; /* 向左移动20px */
  background-color: skyblue;
}
html
<div>
  <div>常规布局元素</div>
  <div class="relative">相对定位元素</div>
  <div>常规布局元素</div>
</div>

TIP

由于 CSS 中的属性常表示“距离”,所以 top: 20px 表示移动后的元素顶部距离原顶部20px,等价于向下移动了 20px

特点:

  1. 保留布局流中占用的原始位置,不影响其他元素
  2. 相对占用的位置进行偏移
  3. 常用于位置的微调

3.2.2. 绝对定位 absolute

css
.card {
  position: relative; /* 将父元素设置为定位容器 */
  margin-top: 2rem; /* 由于绝对定位元素显示在上方,为其预留空间 */
  text-align: center;
  border: 1px solid black;
}

.absolute {
  position: absolute;
  top: -1.3rem;  /* 在容器顶部再向上1.3rem */
  left: 0; /* 与容器左边对齐2rem */

  background-color: skyblue;
  padding: 0 1rem;
  font-family: "华文中宋", sans-serif;
}
html
<div class="card">
  <div>常规布局元素</div>
  <div class="absolute">绝对定位元素</div>
  <div>常规布局元素</div>
</div>

特点:

  1. 脱离文档流,父元素可能“塌陷”
  2. 固定容器
  3. 常和伪类共同使用实现卡片图标、标题等

WARNING

绝对定位元素的参考标准为最近的定位祖先元素(设置 position: relative; 等),否则会导致只能以视口为参考!

3.2.3. 固定定位 fixed

css
.fixed {
  position: fixed;

  top: 0;
  width: 100%;
  background: #dddddd;
  z-index: 999;
}
html
<header class="fixed">
  🚀 固定导航栏
</header>

<!-- 页面主要内容 -->
<div style="padding-top: 60px; min-height: 120vh; padding: 2rem;">
  <p>向下滚动查看固定效果...</p>
  <p>这个导航栏会始终固定在浏览器窗口顶部</p>
</div>

特点:

  1. 相对于浏览器视口定位,不随页面滚动移动
  2. 脱离文档流,不占用原有布局空间
  3. 常用于固定导航栏、侧边栏等始终可见的元素

3.2.4. 粘性定位 sticky

css
.sticky-header {
  position: sticky;
  top: 0; /* 触发粘性定位的临界点 */
  background: #dddddd;
  padding: 4px;
  z-index: 1000;
}

.content {
  position: relative;
  min-height: 120vh;
}
html
<div class="content">
  <p>滚动页面查看标题固定效果...</p>
  <div class="sticky-header">1.1 吸顶标题</div>
  <p>1.1.1 滚动页面查看标题固定效果...</p>
  <p>1.1.2 滚动页面查看标题固定效果...</p>
  <p>1.1.3 滚动页面查看标题固定效果...</p>
</div>

特点:

  1. 结合相对定位与固定定位:初始在文档流中,滚动到指定位置后固定
  2. 参考坐标系为最近的定位祖先元素或视口
  3. 需设置 top/right/bottom/left 属性触发固定效果
  4. 常用于吸顶导航、侧边浮动按钮等场景

3.2.5. 四大定位模式对比

定位模式position 属性值参考坐标系是否脱离文档流核心特点常见用途
相对定位relative自身原始位置原位保留,偏移自身位置微调元素位置
绝对定位absolute最近定位祖先/视口固定在容器中,父容器需定位图标定位、弹窗
固定定位fixed浏览器视口相对视口固定,滚动不移动固定导航栏、侧边栏
粘性定位sticky最近定位祖先/视口滚动后脱离滚动触发固定,结合相对和固定定位吸顶标题、浮动按钮

3.2.6. 层叠上下文 z-index

核心概念:层叠上下文(Stacking Context)决定了元素的绘制顺序,z-index 属性通过控制元素在层叠上下文中的层级实现前后覆盖效果

特点说明

  1. 仅对定位元素生效:只有设置了 position: relative/absolute/fixed/sticky 的元素,z-index 才有效
  2. 独立层叠上下文:当元素满足以下条件时会创建新层叠上下文:
    • position 值为 relative/absolute/fixed/stickyz-indexauto
    • opacity 值小于 1
    • transformfilter 等属性使用非none
  3. 父子层级隔离:子元素的层级始终在父元素层叠上下文内部比较,不会与其它层叠上下文的元素直接比较

示例代码

css
/* 正确使用:固定定位弹窗覆盖其他内容 */
.modal {
  position: fixed;
  z-index: 1000;
  background: white;
  border: 1px solid #666;
}

/* 父元素创建新层叠上下文 */
.parent {
  position: relative;
  z-index: 500; /* 创建新层叠上下文 */
}

.child {
  position: absolute;
  z-index: 2000; /* 实际层级为 500 内的 2000,而非全局 2000 */
}
html
<div style="position: relative; z-index: 1; background: #f0f0f0; padding: 20px;">
  <!-- 普通元素(z-index无效) -->
  <div style="background: #ffcccc; padding: 10px;">非定位元素 (z-index: auto)</div>

  <!-- 父级层叠上下文 -->
  <div class="parent" style="width: 200px; height: 200px; background: #add8e6; position: relative; z-index: 500;">
    <div class="child" style="background: #ff4444; width: 100px; height: 100px; position: absolute; top: 50px; left: 50px; z-index: 2000;">
      子元素 (z-index: 2000)
    </div>
    <!-- 父级内部元素 -->
    <div style="background: #90ee90; position: absolute; z-index: 1000;">
      父级内其他元素 (z-index: 1000)
    </div>
  </div>

  <!-- 高层级元素 -->
  <div style="position: absolute; z-index: 1500; background: #ffff00; right: 0; top: 0;">
    外部元素 (z-index: 1500)
  </div>
</div>

<!-- 固定定位弹窗 -->
<div class="modal" style="right: 20px; bottom: 20px; padding: 20px;">
  固定弹窗 (z-index: 1000)
</div>

常见问题

  1. 非定位元素设置 z-index 完全无效
  2. z-index同一层叠上下文中才生效

最佳实践

  1. 使用 分段数值(如 100, 200, 1000)预留调整空间
  2. 通过父元素创建独立层叠上下文管理复杂层级
  3. 避免过度依赖高 z-index 值(如 9999),可能导致层级混乱

3.3. 🌟 flex 弹性盒布局

传统布局像摆积木,flex 布局像橡皮筋——能自动伸缩适应空间!还记得垂直居中难问题吗?flex 一招解决。

WARNING

本节内容比较复杂,建议同时参考 MDN 教程:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_flexible_box_layout/Basic_concepts_of_flexbox

3.3.1. 弹性容器

核心概念:通过 display: flex 将容器转换为弹性布局容器,控制子元素的排列方式。

主轴是指元素排列的方向,默认水平方向(从左到右)。交叉轴是垂直于主轴的方向(元素高度方向)。

容器核心属性详解

属性作用说明常用值示例
flex-direction主轴方向row(默认水平)
column(垂直方向)
row-reverse
column-reverse
flex-wrap换行规则nowrap(默认不换行)
wrap(允许换行)
wrap-reverse
justify-content主轴对齐方式flex-start(左对齐)
center(居中)
space-between
space-around
align-items交叉轴单行对齐stretch(默认拉伸)
center
flex-start
flex-end
align-content交叉轴多行对齐stretch
center
space-between
space-around
gap元素间距10px 20px(横向/纵向间距)
css
.container {
  display: flex;
  flex-direction: row;    /* 主轴方向 */
  flex-wrap: nowrap;      /* 不换行 */
  justify-content: center;/* 主轴居中 */
  align-items: stretch;   /* 交叉轴拉伸 */
  gap: 10px;              /* 元素间距 */
}
html
<div class="container" style="flex-direction: row; justify-content: space-between; align-items: center; gap: 1rem;">
  <div>左侧元素</div>
  <div>中间元素</div>
  <div>右侧元素</div>
</div>

3.3.2. 弹性项目

关键属性解析

css
.item {
  order: 2;            /* 排列顺序(数值越小越靠前) */
  flex-grow: 1;        /* 自动填充剩余空间(权重值) */
  flex-shrink: 1;      /* 容器不足时缩小比例 */
  flex-basis: 200px;   /* 基础尺寸 */
  flex: 1 0 auto;      /* 简写形式(推荐) */
}

典型场景示例

等宽对齐:

html
<div class="flex-container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
css
.flex-container { display: flex; }
.item { flex: 1; padding: 20px; border: 1px solid #ccc; }

主轴两端对齐:

html
<div class="container">
  <div>左侧</div>
  <div>右侧</div>
</div>
css
.container {
  display: flex;
  justify-content: space-between;
  width: 100%;
}

3.3.3. 最佳实践

垂直居中终极方案

css
/* 容器垂直水平居中 */
.center-container {
  display: flex;
  justify-content: center; /* 主轴 */
  align-items: center;     /* 交叉轴 */
  height: 100vh;          /* 需设置容器高度 */
}

/* 全页面居中方案 */
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

常见问题解决方案

css
/* 避免误区:flex属性写在容器 */
/* ✅ 正确 */
.item { flex: 1; }

/* ❌ 错误 */
.container { flex: 1; }  /* 应写在子元素 */

TIP

使用浏览器开发者工具的"布局"面板可以实时查看主轴/交叉轴方向并更改属性,调试布局更高效!

知识回顾

  1. 默认布局流

    • 块级元素(block)
      • 独占一行,宽度自动撑满父容器
      • 示例:div 默认为块级元素
    • 行内元素(inline)
      • 与同级元素共用一行
      • 宽度由内容决定,不可设置宽高
      • 示例:span 默认为行内元素
    • 文档流特性
      • 块级元素垂直堆叠
      • 行内元素水平排列(空白折叠)
      • 浏览器自动计算布局位置
  2. 定位模式(position

    1. 相对定位 relative
      • 特点:
        • 相对于原始位置偏移
        • 保留原始占位空间
        • 通过 top/right/bottom/left 调整位置
      • 场景:元素微调
    2. 绝对定位 absolute
      • 特点:
        • 脱离文档流
        • 相对于最近定位祖先元素定位
        • 可创建层叠上下文
      • 场景:弹窗、图标定位
    3. 固定定位 fixed
      • 特点:
        • 相对于浏览器视口定位
        • 不随滚动移动
        • 完全脱离文档流
      • 场景:固定导航栏
    4. 粘性定位 sticky
      • 特点:
        • 滚动触发定位模式切换
        • 需设置 top/right/bottom/left 触发条件
        • 结合相对/固定定位特性
      • 场景:吸顶标题栏
  3. Flex弹性布局

    1. 容器核心属性
    属性作用说明典型值示例
    flex-direction主轴方向控制row(默认)/column
    justify-content主轴对齐方式center/space-between
    align-items交叉轴单行对齐stretch/flex-end
    gap元素间距控制10px 20px(横向/纵向)
    1. 项目属性

      • flex-grow:扩展比例(分配剩余空间)
      • flex-shrink:收缩比例(空间不足时)
      • flex-basis:基础尺寸
      • 简写形式:flex: [grow] [shrink] [basis]
    2. 典型应用

      • 垂直居中方案:
        css
        .container {
          display: flex;
          justify-content: center; /* 主轴 */
          align-items: center;     /* 交叉轴 */
        }
      • 响应式布局:通过 flex-wrap: wrap 实现换行
    3. 层叠上下文(z-index

      • 生效条件:必须设置 positionrelative/absolute/fixed/sticky
      • 层叠上下文创建
        • position 非 static 且 z-index≠auto
        • opacity < 1
        • 使用 transform/filter 等属性
      • 层级规则
        • 子元素层级始终在父级创建的层叠上下文中比较
        • 不同层叠上下文的元素层级相互隔离
      • 最佳实践
        • 使用分段数值(如 100, 200)
        • 通过父元素创建独立层级空间
        • 避免过度使用高数值(如 9999)

课后练习

  1. (选择)要让元素相对于浏览器窗口定位,应该用:

    • A. position: relative
    • B. position: absolute
    • C. position: fixed
    • D. position: sticky
  2. (填空)补全代码实现全部居中底部对齐:

    css
    .container {
      display: flex;
      ______: center;
      ______: center;
    }
  3. (纠错)找出错误:

    css
    .box {
      display: flex;
      justify-content: center;
    }
    .box div {
      align-items: center; /* 这里有问题 */
    }
  4. (项目)实现导航栏:

    • 横向排列
    • 调整适当的间隙
    • 永远保持导航项等宽分布
参考答案
  1. C. position: fixed 解析:固定定位元素始终相对于浏览器视口定位,与滚动无关。

  2. align-items, justify-content 解析:前者控制交叉轴对齐,后者控制主轴对齐。

  3. 错误原因:align-items 是容器属性,不能直接用在子元素 .box div 上。修复方案:

    css
    .box {
      display: flex;
      justify-content: center;
      align-items: center; /* 移动到容器中 */
    }
    .box div {
      /* 移除错误代码 */
    }

    或者使用项目属性 align-self

    css
    .box div {
      align-self: center;
    }
  4. 项目题参考:

    css
    /* 导航栏容器 */
    .navbar {
      display: flex;
      gap: 20px; /* 适当间隙 */
      background: #333;
      padding: 10px 0;
    }
    
    /* 导航项等宽分布 */
    .navbar > a {
      flex: 1 1 auto; /* 等分剩余空间 */
      text-align: center;
      padding: 12px 0;
      color: white;
    }

    HTML结构示例

    html
    <nav class="navbar">
      <a href="/">首页</a>
      <a href="/products">产品</a>
      <a href="/about">关于我们</a>
    </nav>

    关键点

    • flex: 1 实现等宽分布
    • gap 属性控制项目间距
    • 默认 flex-direction: row 实现横向排列

Built by Vitepress | Apache 2.0 Licensed