第七篇、定位

5 阅读7分钟

核心概念

定位(position) 是 CSS 实现元素精准布局的核心属性,可打破常规文档流的默认排列规则,让元素基于「自身原位置、父容器、浏览器视口」等参考点灵活定位,是制作弹窗、悬浮导航、元素层叠等交互效果的核心方案。

核心特性

一、文档流控制规则

定位的核心差异首先体现在对「文档流」的影响上,可分为三类:

  1. 完全遵循文档流:仅 static(静态定位),元素按块级 / 行内默认规则排列;

  2. 保留文档流(视觉偏移) :仅 relative(相对定位),元素原物理空间保留,仅视觉上偏移;

  3. 脱离文档流

    • 完全脱离:absolute(绝对定位)、fixed(固定定位),元素不再占据空间,原位置被其他元素填充;
    • 动态脱离:sticky(粘性定位),未触发阈值时遵循文档流,触发后视觉固定(仍受父容器限制)。

二、position 五个取值全解析

取值文档流特性定位参考点核心属性生效规则典型用途
static完全遵循无(仅默认文档流)所有偏移属性、z-index 全部无效所有元素默认状态,无需主动设置
relative保留(仅视觉偏移)自身在文档流中的原始位置偏移属性全部生效、z-index 生效,基于自身原位置偏移微调元素位置、作为绝对定位父容器
absolute完全脱离最近的非 static 祖先元素(无则视口)偏移属性全部生效、z-index 生效,基于参考容器偏移弹窗、悬浮标签、精准对齐元素
fixed完全脱离浏览器视口(不受页面滚动影响)偏移属性全部生效、z-index 生效,基于视口偏移悬浮按钮、固定导航栏、返回顶部
sticky动态切换父容器(未触发)→ 视口(触发后)需指定偏移阈值、父容器 overflowvisible 才生效,z-index 始终生效滚动吸顶导航、表格表头固定
1. static(静态定位)
  • 核心行为:CSS 所有元素的默认定位方式,完全遵循「从上到下、从左到右」的文档流规则;
  • 关键限制top/right/bottom/left/z-index 等定位相关属性全部无效;
  • 使用场景:仅作为「非定位元素」的基准,无需主动设置。
2. relative(相对定位)
  • 核心行为:不脱离文档流,元素原位置保留空白,仅相对于自身默认位置做视觉偏移;
  • 关键特点:偏移不会影响相邻元素布局,仅自身位移;
  • 核心价值:既是微调元素位置的轻量方案,也是 absolute 元素的「参考容器」(最常用场景)。
3. absolute(绝对定位)
  • 核心行为:完全脱离文档流,原位置被其他元素填充;
  • 参考规则:优先参考「最近的已定位祖先元素」(positionstatic),无则参考浏览器视口;
  • 必记技巧:「子绝父相」—— 父元素设 relative,子元素设 absolute,实现子元素相对父容器精准定位。
4. fixed(固定定位)
  • 核心行为:完全脱离文档流,定位参考点始终为浏览器视口,页面滚动时位置不变;
  • 关键特点:与父元素嵌套层级无关,即使嵌套多层仍直接参考视口;
  • 注意事项:移动端需注意兼容,避免被输入法遮挡。
5. sticky(粘性定位)
  • 核心行为:结合 relativefixed 的动态特性,未滚动到阈值时为相对定位,触发后为固定定位;

  • 生效前提

    1. 必须指定 top/bottom/left/right 中的一个阈值;
    2. 父容器 overflow 属性需为 visible(默认值),否则失效;
    3. 不会超出父容器的范围。

三、层叠与偏移规则

  1. 层叠控制(z-index)

    • 仅对非 static 定位元素生效;
    • 取值为整数(正 / 负 / 0),数值越大元素层叠层级越高;
    • 未设置时,后渲染的元素覆盖先渲染的元素。
  2. 偏移优先级

    • 垂直方向:top 优先级 > bottom(同时设置仅 top 生效);
    • 水平方向:left 优先级 > right(同时设置仅 left 生效)。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS 定位五个取值完整示例</title>
    <style>
        /* 通用样式:统一视觉效果 */
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { padding: 20px; padding-bottom: 2000px; color: #333; }
        .demo-card { 
            margin: 40px 0; 
            padding: 25px; 
            border: 1px solid #eee; 
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.05);
        }
        .demo-title { 
            margin-bottom: 20px; 
            font-size: 18px; 
            font-weight: 600; 
            color: #2c3e50;
            border-left: 4px solid #667eea;
            padding-left: 10px;
        }
        .box { 
            width: 100px; 
            height: 100px; 
            text-align: center; 
            line-height: 100px; 
            color: #fff; 
            border-radius: 4px;
        }
        .desc { margin-top: 15px; color: #666; line-height: 1.6; }

        /* 1. static 静态定位 */
        .static-box {
            position: static; /* 默认值,可省略 */
            left: 50px; /* 无效属性 */
            background: #95a5a6;
        }

        /* 2. relative 相对定位 */
        .relative-wrap { 
            border: 1px dashed #ddd; 
            padding: 20px; 
            margin-bottom: 10px;
        }
        .relative-box {
            position: relative;
            left: 30px; /* 相对自身原位置右移30px */
            top: 10px;  /* 相对自身原位置下移10px */
            background: #667eea;
        }

        /* 3. absolute 绝对定位(子绝父相) */
        .absolute-wrap {
            position: relative; /* 作为子元素的参考容器 */
            width: 400px;
            height: 200px;
            background: #f8f9fa;
            border: 1px solid #ddd;
        }
        .absolute-box {
            position: absolute;
            right: 20px; /* 距离父容器右侧20px */
            bottom: 20px; /* 距离父容器底部20px */
            background: #f08080;
        }

        /* 4. fixed 固定定位 */
        .fixed-box {
            position: fixed;
            right: 30px; /* 距离视口右侧30px */
            bottom: 30px; /* 距离视口底部30px */
            background: #28a745;
            border-radius: 50%;
            cursor: pointer;
            z-index: 999; /* 确保在最顶层 */
            transition: background 0.3s;
        }
        .fixed-box:hover { background: #218838; }

        /* 5. sticky 粘性定位 */
        .sticky-box {
            position: sticky;
            top: 20px; /* 触发阈值:距离视口顶部20px时固定 */
            width: 100%;
            height: 50px;
            line-height: 50px;
            background: #ffc107;
            color: #333;
            margin: 10px 0;
        }

        /* 层叠顺序示例 */
        .z-index-wrap {
            position: relative;
            height: 150px;
            margin-top: 20px;
            border: 1px dashed #ddd;
        }
        .z-index-box1 {
            position: absolute;
            left: 50px;
            top: 20px;
            background: rgba(240, 128, 128, 0.8);
            z-index: 1;
        }
        .z-index-box2 {
            position: absolute;
            left: 70px;
            top: 40px;
            background: rgba(102, 126, 234, 0.8);
            z-index: 2;
        }
    </style>
</head>
<body>
    <!-- 1. static 静态定位示例 -->
    <div class="demo-card">
        <div class="demo-title">1. static(静态定位):默认值,仅遵循文档流</div>
        <div class="static-box">static</div>
        <p class="desc">static 是所有元素的默认定位,left: 50px 等偏移属性完全无效,仅按文档流默认规则排列。</p>
    </div>

    <!-- 2. relative 相对定位示例 -->
    <div class="demo-card">
        <div class="demo-title">2. relative(相对定位):相对自身偏移,保留原位置</div>
        <div class="relative-wrap">
            <div class="relative-box">relative</div>
        </div>
        <p class="desc">relative 元素向右/向下偏移,但原位置仍保留(父容器虚线框内的空白),不会影响其他元素布局。</p>
    </div>

    <!-- 3. absolute 绝对定位示例 -->
    <div class="demo-card">
        <div class="demo-title">3. absolute(绝对定位):子绝父相,完全脱离文档流</div>
        <div class="absolute-wrap">
            <div class="absolute-box">absolute</div>
            <p>此文字会填充absolute元素的原位置(因为absolute完全脱离文档流)</p>
        </div>
        <p class="desc">absolute 必须依赖「非static的父元素」定位,否则会参考浏览器视口;子绝父相是最常用的精准定位技巧。</p>
    </div>

    <!-- 4. sticky 粘性定位示例 -->
    <div class="demo-card">
        <div class="demo-title">4. sticky(粘性定位):滚动触发固定,动态切换</div>
        <div class="sticky-box">sticky - 滚动页面我会粘在顶部(top:20px)</div>
        <p class="desc">sticky 未滚动到阈值时是相对定位,触发后变为固定定位,但不会超出父容器范围;需注意父容器overflow必须为visible。</p>
    </div>

    <!-- 5. fixed 固定定位 + 层叠示例 -->
    <div class="demo-card">
        <div class="demo-title">5. fixed(固定定位):相对视口固定 + z-index层叠</div>
        <div class="z-index-wrap">
            <div class="box z-index-box1">z-index:1</div>
            <div class="box z-index-box2">z-index:2</div>
        </div>
        <p class="desc">z-index 仅对非static元素生效,数值越大越在顶层;fixed按钮始终固定在视口右下角,不受页面滚动影响。</p>
    </div>

    <!-- fixed 固定定位按钮 -->
    <div class="box fixed-box"></div>
</body>
</html>