B33. 布局流 定位
3.1. ⭐ 默认布局流
浏览器的最大优势之一是打破了传统的固定宽高的布局,使布局流更加自由。程序员只需设置 CSS 属性,具体的位置计算交给浏览器便可。
块级与行内元素:
/* 块级元素独占一行 */
div { display: block; }
/* 行内元素共存一行 */
span { display: inline; }
文档流特性:块级另起一行,连续的行级元素共用一行,存在空白折叠现象。
<!-- 默认布局演示 -->
<div>我会占据整行</div>
<span>我们</span>
<span>排在同一行</span>
3.2. 🌟 定位 position 属性
想让元素像便利贴一样"贴"在特定位置?定位属性就是你的布局瑞士军刀。
position
属性控制元素在文档流中的定位方式,分相对定位、绝对定位、固定定位、粘性定位。
3.2.1. 相对定位 relative
.relative {
position: relative;
top: 10px; /* 向下移动10px */
right: -20px; /* 向左移动20px */
background-color: skyblue;
}
<div>
<div>常规布局元素</div>
<div class="relative">相对定位元素</div>
<div>常规布局元素</div>
</div>
TIP
由于 CSS 中的属性常表示“距离”,所以 top: 20px
表示移动后的元素顶部距离原顶部为 20px
,等价于向下移动了 20px
。
特点:
- 保留在布局流中占用的原始位置,不影响其他元素
- 相对占用的位置进行偏移
- 常用于位置的微调
3.2.2. 绝对定位 absolute
.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;
}
<div class="card">
<div>常规布局元素</div>
<div class="absolute">绝对定位元素</div>
<div>常规布局元素</div>
</div>
特点:
- 脱离文档流,父元素可能“塌陷”
- 固定在容器中
- 常和伪类共同使用实现卡片图标、标题等
WARNING
绝对定位元素的参考标准为最近的定位祖先元素(设置 position: relative;
等),否则会导致只能以视口为参考!
3.2.3. 固定定位 fixed
.fixed {
position: fixed;
top: 0;
width: 100%;
background: #dddddd;
z-index: 999;
}
<header class="fixed">
🚀 固定导航栏
</header>
<!-- 页面主要内容 -->
<div style="padding-top: 60px; min-height: 120vh; padding: 2rem;">
<p>向下滚动查看固定效果...</p>
<p>这个导航栏会始终固定在浏览器窗口顶部</p>
</div>
特点:
- 相对于浏览器视口定位,不随页面滚动移动
- 脱离文档流,不占用原有布局空间
- 常用于固定导航栏、侧边栏等始终可见的元素
3.2.4. 粘性定位 sticky
.sticky-header {
position: sticky;
top: 0; /* 触发粘性定位的临界点 */
background: #dddddd;
padding: 4px;
z-index: 1000;
}
.content {
position: relative;
min-height: 120vh;
}
<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>
特点:
- 结合相对定位与固定定位:初始在文档流中,滚动到指定位置后固定
- 参考坐标系为最近的定位祖先元素或视口
- 需设置
top/right/bottom/left
属性触发固定效果 - 常用于吸顶导航、侧边浮动按钮等场景
3.2.5. 四大定位模式对比
定位模式 | position 属性值 | 参考坐标系 | 是否脱离文档流 | 核心特点 | 常见用途 |
---|---|---|---|---|---|
相对定位 | relative | 自身原始位置 | 否 | 原位保留,偏移自身位置 | 微调元素位置 |
绝对定位 | absolute | 最近定位祖先/视口 | 是 | 固定在容器中,父容器需定位 | 图标定位、弹窗 |
固定定位 | fixed | 浏览器视口 | 是 | 相对视口固定,滚动不移动 | 固定导航栏、侧边栏 |
粘性定位 | sticky | 最近定位祖先/视口 | 滚动后脱离 | 滚动触发固定,结合相对和固定定位 | 吸顶标题、浮动按钮 |
3.2.6. 层叠上下文 z-index
核心概念:层叠上下文(Stacking Context)决定了元素的绘制顺序,z-index
属性通过控制元素在层叠上下文中的层级实现前后覆盖效果。
特点说明:
- 仅对定位元素生效:只有设置了
position: relative/absolute/fixed/sticky
的元素,z-index
才有效 - 独立层叠上下文:当元素满足以下条件时会创建新层叠上下文:
position
值为relative/absolute/fixed/sticky
且z-index
≠auto
opacity
值小于 1transform
、filter
等属性使用非none
值
- 父子层级隔离:子元素的层级始终在父元素层叠上下文内部比较,不会与其它层叠上下文的元素直接比较
示例代码:
/* 正确使用:固定定位弹窗覆盖其他内容 */
.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 */
}
<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>
常见问题:
- 非定位元素设置
z-index
完全无效 z-index
在同一层叠上下文中才生效
最佳实践:
- 使用 分段数值(如 100, 200, 1000)预留调整空间
- 通过父元素创建独立层叠上下文管理复杂层级
- 避免过度依赖高
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 (横向/纵向间距) |
.container {
display: flex;
flex-direction: row; /* 主轴方向 */
flex-wrap: nowrap; /* 不换行 */
justify-content: center;/* 主轴居中 */
align-items: stretch; /* 交叉轴拉伸 */
gap: 10px; /* 元素间距 */
}
<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. 弹性项目
关键属性解析:
.item {
order: 2; /* 排列顺序(数值越小越靠前) */
flex-grow: 1; /* 自动填充剩余空间(权重值) */
flex-shrink: 1; /* 容器不足时缩小比例 */
flex-basis: 200px; /* 基础尺寸 */
flex: 1 0 auto; /* 简写形式(推荐) */
}
典型场景示例:
等宽对齐:
<div class="flex-container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
.flex-container { display: flex; }
.item { flex: 1; padding: 20px; border: 1px solid #ccc; }
主轴两端对齐:
<div class="container">
<div>左侧</div>
<div>右侧</div>
</div>
.container {
display: flex;
justify-content: space-between;
width: 100%;
}
3.3.3. 最佳实践
垂直居中终极方案:
/* 容器垂直水平居中 */
.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;
}
常见问题解决方案:
/* 避免误区:flex属性写在容器 */
/* ✅ 正确 */
.item { flex: 1; }
/* ❌ 错误 */
.container { flex: 1; } /* 应写在子元素 */
TIP
使用浏览器开发者工具的"布局"面板可以实时查看主轴/交叉轴方向并更改属性,调试布局更高效!
知识回顾
默认布局流
- 块级元素(block)
- 独占一行,宽度自动撑满父容器
- 示例:
div
默认为块级元素
- 行内元素(inline)
- 与同级元素共用一行
- 宽度由内容决定,不可设置宽高
- 示例:
span
默认为行内元素
- 文档流特性
- 块级元素垂直堆叠
- 行内元素水平排列(空白折叠)
- 浏览器自动计算布局位置
- 块级元素(block)
定位模式(
position
)- 相对定位
relative
- 特点:
- 相对于原始位置偏移
- 保留原始占位空间
- 通过
top/right/bottom/left
调整位置
- 场景:元素微调
- 特点:
- 绝对定位
absolute
- 特点:
- 脱离文档流
- 相对于最近定位祖先元素定位
- 可创建层叠上下文
- 场景:弹窗、图标定位
- 特点:
- 固定定位
fixed
- 特点:
- 相对于浏览器视口定位
- 不随滚动移动
- 完全脱离文档流
- 场景:固定导航栏
- 特点:
- 粘性定位
sticky
- 特点:
- 滚动触发定位模式切换
- 需设置
top/right/bottom/left
触发条件 - 结合相对/固定定位特性
- 场景:吸顶标题栏
- 特点:
- 相对定位
Flex弹性布局
- 容器核心属性
属性 作用说明 典型值示例 flex-direction
主轴方向控制 row
(默认)/column
justify-content
主轴对齐方式 center
/space-between
align-items
交叉轴单行对齐 stretch
/flex-end
gap
元素间距控制 10px 20px
(横向/纵向)项目属性
flex-grow
:扩展比例(分配剩余空间)flex-shrink
:收缩比例(空间不足时)flex-basis
:基础尺寸- 简写形式:
flex: [grow] [shrink] [basis]
典型应用
- 垂直居中方案:css
.container { display: flex; justify-content: center; /* 主轴 */ align-items: center; /* 交叉轴 */ }
- 响应式布局:通过
flex-wrap: wrap
实现换行
- 垂直居中方案:
层叠上下文(
z-index
)- 生效条件:必须设置
position
为relative/absolute/fixed/sticky
- 层叠上下文创建:
position
非 static 且z-index
≠autoopacity
< 1- 使用
transform
/filter
等属性
- 层级规则:
- 子元素层级始终在父级创建的层叠上下文中比较
- 不同层叠上下文的元素层级相互隔离
- 最佳实践:
- 使用分段数值(如 100, 200)
- 通过父元素创建独立层级空间
- 避免过度使用高数值(如 9999)
- 生效条件:必须设置
课后练习
(选择)要让元素相对于浏览器窗口定位,应该用:
- A.
position: relative
- B.
position: absolute
- C.
position: fixed
- D.
position: sticky
- A.
(填空)补全代码实现全部居中底部对齐:
css.container { display: flex; ______: center; ______: center; }
(纠错)找出错误:
css.box { display: flex; justify-content: center; } .box div { align-items: center; /* 这里有问题 */ }
(项目)实现导航栏:
- 横向排列
- 调整适当的间隙
- 永远保持导航项等宽分布
参考答案
C.
position: fixed
解析:固定定位元素始终相对于浏览器视口定位,与滚动无关。align-items
,justify-content
解析:前者控制交叉轴对齐,后者控制主轴对齐。错误原因:
align-items
是容器属性,不能直接用在子元素.box div
上。修复方案:css.box { display: flex; justify-content: center; align-items: center; /* 移动到容器中 */ } .box div { /* 移除错误代码 */ }
或者使用项目属性
align-self
:css.box div { align-self: center; }
项目题参考:
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
实现横向排列