跳到主要内容

CSS 定位

CSS 定位(position)是一种将元素从正常文档流中移除并放置在指定位置的布局方式。与 Flexbox 和 Grid 这种现代布局系统不同,定位更像是"钉"住元素,适合创建浮动效果、模态框、工具提示等特殊场景。

正常文档流

在了解定位之前,需要先理解"正常文档流"的概念。默认情况下,块级元素从上到下堆叠,行内元素从左到右排列,这就是正常文档流。元素在流中的位置由其前面的兄弟元素决定。

定位允许我们将元素从正常流中移除,放置在任意位置。这会影响其他元素对它的"感知",从而实现层叠效果。

position 属性

position 属性决定元素的定位方式:

.static { position: static; }
.relative { position: relative; }
.absolute { position: absolute; }
.fixed { position: fixed; }
.sticky { position: sticky; }

static 静态定位

static 是默认值,元素按照正常文档流布局。此时 toprightbottomleftz-index 属性无效。

.box {
position: static; /* 默认值 */
}

大多数情况下不需要显式设置 position: static,除非需要覆盖之前的定位设置。

relative 相对定位

相对定位的元素保持在正常文档流中,但可以通过 toprightbottomleft 属性相对于其原始位置进行偏移。偏移不会影响其他元素的位置。

.box {
position: relative;
top: 20px; /* 向下偏移 20px */
left: 30px; /* 向右偏移 30px */
}

注意 top 表示元素顶部边界向下移动的距离,正值向下移动。同理 left 正值向右移动。

相对定位的两个重要用途:

  1. 微调位置:稍微移动元素而不影响布局
.icon {
position: relative;
top: 2px; /* 图标稍微下移,与文字对齐 */
}
  1. 作为定位参考:为内部绝对定位的元素提供定位上下文
.container {
position: relative; /* 子元素 absolute 相对于此定位 */
}

.tooltip {
position: absolute;
bottom: 100%; /* 在容器上方 */
}

absolute 绝对定位

绝对定位将元素从正常文档流中移除,不再占据空间。其他元素会忽略它的存在,就像它不存在一样。元素的位置相对于最近的定位祖先(非 static 的祖先)进行偏移,如果没有定位祖先,则相对于初始包含块(通常是视口)。

.parent {
position: relative; /* 成为定位祖先 */
}

.child {
position: absolute;
top: 10px;
right: 10px; /* 相对于父元素右上角 */
}

常见用法:

1. 相对于父元素定位

.card {
position: relative;
}

.badge {
position: absolute;
top: -10px;
right: -10px; /* 角标 */
}

2. 覆盖整个父元素

.overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0; /* 或简写 inset: 0 */
background: rgba(0, 0, 0, 0.5);
}

3. 居中定位

.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

绝对定位元素的尺寸可以由 topbottom 同时设置来拉伸高度,或由 leftright 同时设置来拉伸宽度:

.full-height {
position: absolute;
top: 0;
bottom: 0; /* 高度撑满父元素 */
width: 200px;
}

fixed 固定定位

固定定位将元素相对于视口定位,页面滚动时元素保持在固定位置。固定定位元素同样脱离正常文档流。

.header {
position: fixed;
top: 0;
left: 0;
right: 0; /* 固定在顶部 */
z-index: 100;
}

.back-to-top {
position: fixed;
bottom: 20px;
right: 20px; /* 返回顶部按钮 */
}

常见用法:

固定导航栏

.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 60px;
}

/* 页面内容需要预留顶部空间 */
.main {
margin-top: 60px;
}

模态框遮罩

.modal-overlay {
position: fixed;
inset: 0; /* 等同于 top: 0; right: 0; bottom: 0; left: 0 */
background: rgba(0, 0, 0, 0.5);
}

.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

注意:如果祖先元素设置了 transformperspectivefilter 属性(值不为 none),固定定位会相对于该祖先而不是视口。

sticky 粘性定位

粘性定位是相对定位和固定定位的混合体。元素在滚动到指定阈值前表现为相对定位,到达阈值后表现为固定定位。

.sticky-header {
position: sticky;
top: 0; /* 滚动到顶部时固定 */
}

粘性定位常用于:

粘性标题

.section-title {
position: sticky;
top: 60px; /* 考虑固定导航栏高度 */
background: white;
z-index: 10;
}

粘性侧边栏

.sidebar {
position: sticky;
top: 80px;
height: fit-content;
}

粘性定位的几个要点:

  • 必须指定至少一个阈值(toprightbottomleft
  • 元素相对于最近的滚动祖先定位
  • 元素被限制在其父元素范围内,不会溢出
<div class="container" style="height: 500px; overflow: auto;">
<h2 style="position: sticky; top: 0; background: white;">标题 A</h2>
<p>内容...</p>
<h2 style="position: sticky; top: 0; background: white;">标题 B</h2>
<p>内容...</p>
</div>

定位属性

top、right、bottom、left

这四个属性设置定位元素的偏移:

.box {
position: absolute;
top: 10px; /* 顶部距离包含块顶部 10px */
right: 20px; /* 右侧距离包含块右侧 20px */
bottom: 10px;
left: 20px;
}

可以使用 inset 简写:

.box {
inset: 10px 20px; /* 上下 左右 */
inset: 10px 20px 30px; /* 上 左右 下 */
inset: 10px 20px 30px 40px; /* 上 右 下 左 */
}

z-index 层叠顺序

z-index 控制定位元素在 Z 轴上的堆叠顺序。数值越大,越靠近用户(在上层)。

.back { z-index: 1; }
.middle { z-index: 2; }
.front { z-index: 3; }

z-index 只对定位元素(非 static)生效。

层叠上下文是一个重要概念。当元素满足以下条件之一时,会创建新的层叠上下文:

  • position 不为 staticz-index 不为 auto
  • opacity 小于 1
  • transformfilterperspective 等属性不为 none
  • position: fixedposition: sticky

层叠上下文内部的元素的 z-index 只在该上下文内比较,不会与外部元素比较。

.parent {
position: relative;
z-index: 1; /* 创建层叠上下文 */
}

.child {
position: absolute;
z-index: 9999; /* 只在 parent 内部有效 */
}

常见布局模式

固定页头与主内容区

.header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 60px;
z-index: 100;
}

.main {
margin-top: 60px; /* 为固定头部留出空间 */
}

图片上的文字覆盖

.figure {
position: relative;
}

.figure img {
display: block;
width: 100%;
}

.figure figcaption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
}

角标和徽章

.badge-container {
position: relative;
display: inline-block;
}

.badge {
position: absolute;
top: -8px;
right: -8px;
min-width: 18px;
height: 18px;
border-radius: 9px;
background: red;
color: white;
font-size: 12px;
text-align: center;
line-height: 18px;
}

工具提示

.tooltip-container {
position: relative;
}

.tooltip {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
margin-bottom: 8px;
padding: 8px 12px;
background: #333;
color: white;
font-size: 12px;
white-space: nowrap;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s;
}

.tooltip-container:hover .tooltip {
opacity: 1;
visibility: visible;
}

下拉菜单

.dropdown {
position: relative;
}

.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
min-width: 200px;
background: white;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
opacity: 0;
visibility: hidden;
}

.dropdown:hover .dropdown-menu {
opacity: 1;
visibility: visible;
}

模态框

.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
}

.modal-content {
background: white;
max-width: 500px;
width: 90%;
max-height: 90vh;
overflow: auto;
}

小结

这一章我们学习了:

  • 正常文档流和定位的基本概念
  • position 的五种值:static、relative、absolute、fixed、sticky
  • 定位属性:top、right、bottom、left、z-index
  • 层叠上下文的概念
  • 常见定位布局模式

定位是 CSS 布局的重要补充,适合处理元素脱离正常流的场景。记住几个关键点:

  • 相对定位作为定位上下文,为绝对定位子元素提供参考
  • 绝对定位相对于最近的定位祖先
  • 固定定位相对于视口
  • 粘性定位在滚动时切换定位模式
  • z-index 只在定位元素间生效

下一章我们将学习响应式设计,让网页适配各种屏幕尺寸。