CSS position: sticky 属性值

CSS position 属性 CSS position 属性


position: sticky 是 CSS 定位属性中相对较新的值。粘性定位相对定位固定定位的混合体:元素在跨越指定的阈值之前表现得像相对定位,之后表现得像固定定位。

这是实现"吸顶导航"、"表格标题固定"等效果的现代解决方案。

单词释义sticky 意为"粘性的",表示元素会"粘"在某个位置不动。


基本语法

position: sticky 需要配合至少一个方向(toprightbottomleft)的阈值来指定"粘性"生效的位置。

/* 语法 */
position: sticky;

/* 常用组合:滚动到距离顶部 10px 时固定 */
.sticky-header {
    position: sticky;
    top: 10px;
}

工作原理

sticky 定位的工作方式可以分解为两个阶段:

阶段 1:正常滚动(相对定位)

当元素在视口中未达到指定的阈值时,元素按照正常文档流布局,会随页面滚动移动。此时它相当于 position: relative

阶段 2:固定显示(固定定位)

当元素滚动到超过指定的阈值时,元素固定在那个位置,不再随页面滚动。此时它相当于 position: fixed

阈值条件

属性 触发条件
top: 10px 元素顶部距离视口顶部 > 10px 时固定
bottom: 10px 元素底部距离视口底部 > 10px 时固定
left: 10px 元素左边距离视口左边 > 10px 时固定
right: 10px 元素右边距离视口右边 > 10px 时固定

核心特性

特性 1:双向行为

sticky 兼具 relative 和 fixed 的特点,是两者的完美结合。

特性 2:不需要父元素设置定位

absolute 不同,sticky 元素不需要父元素设置任何定位属性。

特性 3:父容器overflow的限制

如果父元素设置了 overflow: hiddenoverflow: autooverflow: scroll,sticky 定位可能会失效。

特性 4:激活 z-index

sticky 定位会激活 z-index 属性。


实例

让我们通过实例深入理解 position: sticky 的特性。

示例 1:吸顶导航栏

这是 sticky 定位最常见的应用:实现吸顶导航栏。

实例

<!DOCTYPE html>
<html>
<head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            font-family: Arial, sans-serif;
        }

        /* 页面顶部大图区域 */
        .hero {
            height: 300px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-size: 36px;
            font-weight: bold;
        }

        /* 粘性导航栏 */
        .sticky-nav {
            position: sticky;
            top: 0;  /* 滚动到顶部时固定 */
            background-color: #2c3e50;
            color: white;
            padding: 15px 30px;
            z-index: 100;
        }

        .sticky-nav ul {
            list-style: none;
            display: flex;
            gap: 30px;
            max-width: 800px;
            margin: 0 auto;
        }

        .sticky-nav a {
            color: white;
            text-decoration: none;
        }

        /* 内容区域 */
        .content {
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }

        .section {
            margin-bottom: 40px;
            padding: 20px;
            background-color: #f5f5f5;
            border-radius: 4px;
        }

        .tall-spacer {
            height: 1500px;
        }
    </style>
</head>
<body>
    <div class="hero">
        RUNOOB 教程
    </div>

    <nav class="sticky-nav">
        <ul>
            <li><a href="#">首页</a></li>
            <li><a href="#">教程</a></li>
            <li><a href="#">实例</a></li>
            <li><a href="#">工具</a></li>
            <li><a href="#">关于</a></li>
        </ul>
    </nav>

    <div class="content">
        <div class="section">
            <h2>第一章:入门</h2>
            <p>这是第一章的内容。向下滚动查看导航栏的粘性效果。</p>
        </div>
        <div class="section">
            <h2>第二章:进阶</h2>
            <p>这是第二章的内容。</p>
        </div>
        <div class="section">
            <h2>第三章:高级</h2>
            <p>这是第三章的内容。</p>
        </div>
        <div class="section">
            <h2>第四章:实战</h2>
            <p>这是第四章的内容。</p>
        </div>
        <div class="section">
            <h2>第五章:项目</h2>
            <p>这是第五章的内容。</p>
        </div>
        <div class="tall-spacer"></div>
    </div>
</body>
</html>

示例 2:表格标题行固定

sticky 定位非常适合用于固定表格的表头:

实例

<!DOCTYPE html>
<html>
<head>
    <style>
        .table-container {
            max-width: 600px;
            max-height: 300px;
            overflow-y: auto;  /* 需要设置 overflow 才能看到固定效果 */
            border: 2px solid #ddd;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        /* 表头使用 sticky 定位 */
        th {
            position: sticky;
            top: 0;
            background-color: #3498db;
            color: white;
            padding: 12px;
            text-align: left;
        }

        td {
            padding: 10px 12px;
            border-bottom: 1px solid #eee;
        }

        tr:nth-child(even) {
            background-color: #f9f9f9;
        }
    </style>
</head>
<body>
    <h2>学生成绩表</h2>
    <p>向下滚动查看表头固定效果:</p>

    <div class="table-container">
        <table>
            <thead>
                <tr>
                    <th>学号</th>
                    <th>姓名</th>
                    <th>语文</th>
                    <th>数学</th>
                    <th>英语</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>001</td>
                    <td>张三</td>
                    <td>85</td>
                    <td>92</td>
                    <td>88</td>
                </tr>
                <tr>
                    <td>002</td>
                    <td>李四</td>
                    <td>90</td>
                    <td>87</td>
                    <td>95</td>
                </tr>
                <tr>
                    <td>003</td>
                    <td>王五</td>
                    <td>78</td>
                    <td>85</td>
                    <td>82</td>
                </tr>
                <tr>
                    <td>004</td>
                    <td>赵六</td>
                    <td>92</td>
                    <td>88</td>
                    <td>90</td>
                </tr>
                <tr>
                    <td>005</td>
                    <td>钱七</td>
                    <td>88</td>
                    <td>91</td>
                    <td>87</td>
                </tr>
                <tr>
                    <td>006</td>
                    <td>孙八</td>
                    <td>85</td>
                    <td>89</td>
                    <td>93</td>
                </tr>
                <tr>
                    <td>007</td>
                    <td>周九</td>
                    <td>80</td>
                    <td>86</td>
                    <td>84</td>
                </tr>
                <tr>
                    <td>008</td>
                    <td>吴十</td>
                    <td>91</td>
                    <td>93</td>
                    <td>89</td>
                </tr>
                <tr>
                    <td>009</td>
                    <td>郑十一</td>
                    <td>87</td>
                    <td>85</td>
                    <td>88</td>
                </tr>
                <tr>
                    <td>010</td>
                    <td>陈十二</td>
                    <td>89</td>
                    <td>90</td>
                    <td>91</td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
</html>

示例 3:侧边栏粘性效果

当页面内容很长时,可以让侧边栏在滚动到一定位置后固定:

实例

<!DOCTYPE html>
<html>
<head>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: Arial, sans-serif;
        }

        .container {
            display: grid;
            grid-template-columns: 1fr 200px;
            max-width: 900px;
            margin: 0 auto;
        }

        .main-content {
            padding: 20px;
        }

        /* 粘性侧边栏 */
        .sidebar {
            position: sticky;
            top: 20px;  /* 距离顶部 20px 时固定 */
            height: fit-content;
            background-color: #3498db;
            color: white;
            padding: 15px;
            border-radius: 4px;
        }

        .content-block {
            background-color: #f5f5f5;
            padding: 20px;
            margin-bottom: 20px;
            border-radius: 4px;
        }

        .tall-block {
            height: 800px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="main-content">
            <h1>主内容区域</h1>
            <p>向下滚动查看侧边栏的粘性效果。</p>

            <div class="content-block">
                <h2>内容区域 1</h2>
                <p>这是第一段内容。</p>
            </div>
            <div class="content-block">
                <h2>内容区域 2</h2>
                <p>这是第二段内容。</p>
            </div>
            <div class="content-block">
                <h2>内容区域 3</h2>
                <p>这是第三段内容。</p>
            </div>
            <div class="content-block tall-block">
                <h2>长内容区域</h2>
                <p>这是比较长的内容区域,用来展示侧边栏的粘性效果。</p>
                <p>继续向下滚动...</p>
            </div>
            <div class="content-block">
                <h2>内容区域 4</h2>
                <p>这是第四段内容。</p>
            </div>
            <div class="content-block">
                <h2>内容区域 5</h2>
                <p>这是第五段内容。</p>
            </div>
        </div>

        <aside class="sidebar">
            <h3>侧边栏</h3>
            <p>我会粘在右侧</p>
            <p>直到滚动出视口</p>
        </aside>
    </div>
</body>
</html>

示例 4:分段标题固定

sticky 定位非常适合用于文章的分段标题固定:

实例

<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }

        /* 分段标题固定 */
        .chapter-title {
            position: sticky;
            top: 0;
            background-color: #2c3e50;
            color: white;
            padding: 15px;
            margin: 20px 0 10px;
            border-radius: 4px;
        }

        .content {
            padding: 0 15px;
            line-height: 1.8;
            margin-bottom: 30px;
        }

        .tall-content {
            height: 600px;
        }
    </style>
</head>
<body>
    <h1>书籍章节示例</h1>

    <div class="chapter-title">第一章:初识编程</div>
    <div class="content">
        <p>编程是一门创造性的艺术。本章将带你了解什么是编程,以及为什么学习编程如此重要。</p>
    </div>

    <div class="chapter-title">第二章:环境搭建</div>
    <div class="content tall-content">
        <p>在开始编写代码之前,我们需要先搭建开发环境。本章介绍如何安装必要的工具和配置开发环境。</p>
        <p>内容区域足够长,以便产生滚动效果。</p>
    </div>

    <div class="chapter-title">第三章:基础语法</div>
    <div class="content">
        <p>本章介绍编程语言的基础语法,包括变量、数据类型、运算符等核心概念。</p>
    </div>

    <div class="chapter-title">第四章:控制结构</div>
    <div class="content tall-content">
        <p>控制结构决定了程序的执行顺序。介绍条件语句和循环语句的使用方法。</p>
    </div>

    <div class="chapter-title">第五章:函数</div>
    <div class="content">
        <p>函数是组织代码的基本单元。本章讲解如何定义和调用函数。</p>
    </div>
</body>
</html>

示例 5:双向粘性定位

可以同时设置水平和垂直方向的粘性定位:

实例

<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            font-family: Arial, sans-serif;
        }

        .calendar {
            width: 350px;
            border: 2px solid #ddd;
        }

        /* 星期标题行 - 顶部固定 */
        .weekday {
            position: sticky;
            top: 0;
            background-color: #3498db;
            color: white;
            padding: 10px;
            text-align: center;
        }

        /* 时间列 - 左侧固定 */
        .time-label {
            position: sticky;
            left: 0;
            background-color: #ecf0f1;
            padding: 20px 10px;
            border-right: 1px solid #ddd;
            font-weight: bold;
        }

        /* 日期单元格 */
        .day-cell {
            padding: 20px;
            border: 1px solid #eee;
            text-align: center;
        }

        .day-cell:nth-child(2) {
            position: sticky;
            left: 50px;  /* 时间列宽度 + 边框 */
            background-color: white;
        }

        /* 模拟日历网格 */
        .calendar-grid {
            display: grid;
            grid-template-columns: 50px repeat(5, 1fr);
        }
    </style>
</head>
<body>
    <h2>课程表(双向粘性)</h2>
    <p>向下和向右滚动查看效果:</p>

    <div class="calendar">
        <div class="calendar-grid">
            <!-- 星期标题行 -->
            <div></div>  <!-- 时间列空白 -->
            <div class="weekday">周一</div>
            <div class="weekday">周二</div>
            <div class="weekday">周三</div>
            <div class="weekday">周四</div>
            <div class="weekday">周五</div>

            <!-- 时间行 1 -->
            <div class="time-label">8:00</div>
            <div class="day-cell">数学</div>
            <div class="day-cell">语文</div>
            <div class="day-cell">英语</div>
            <div class="day-cell">物理</div>
            <div class="day-cell">化学</div>

            <!-- 时间行 2 -->
            <div class="time-label">9:00</div>
            <div class="day-cell">英语</div>
            <div class="day-cell">数学</div>
            <div class="day-cell">化学</div>
            <div class="day-cell">语文</div>
            <div class="day-cell">物理</div>

            <!-- 时间行 3 -->
            <div class="time-label">10:00</div>
            <div class="day-cell">物理</div>
            <div class="day-cell">化学</div>
            <div class="day-cell">数学</div>
            <div class="day-cell">英语</div>
            <div class="day-cell">语文</div>

            <!-- 时间行 4 -->
            <div class="time-label">11:00</div>
            <div class="day-cell">语文</div>
            <div class="day-cell">物理</div>
            <div class="day-cell">数学</div>
            <div class="day-cell">化学</div>
            <div class="day-cell">英语</div>
        </div>
    </div>
</body>
</html>

注意事项

浏览器兼容性:position: sticky 在现代浏览器中得到良好支持,但 IE 浏览器完全不支持。如果需要支持 IE,需要使用 JavaScript 或其他 polyfill 方案作为降级处理。

父元素 overflow 的影响

如果父元素设置了以下属性,sticky 定位会失效

overflow: hidden
overflow: auto
overflow: scroll

必须设置阈值

至少需要设置 toprightbottomleft 中的一个,否则 sticky 不会生效(元素会按照正常文档流布局)。

阈值计算

sticky 定位的阈值是相对于视口计算的,而不是父元素。


与其它定位值的对比

定位值 是否脱离文档流 固定条件 兼容性
static 所有浏览器
relative 所有浏览器
absolute 所有浏览器
fixed 始终固定 所有浏览器
sticky 阈值前否,阈值后是 滚动超过阈值 现代浏览器(IE 不支持)

常见应用场景

场景 1:吸顶导航

.nav {
    position: sticky;
    top: 0;
}

场景 2:表格表头固定

th {
    position: sticky;
    top: 0;
}

场景 3:侧边栏固定

.sidebar {
    position: sticky;
    top: 20px;
}

场景 4:文章章节标题

.chapter-header {
    position: sticky;
    top: 0;
    background: white;  /* 固定时显示背景 */
}

总结

position: sticky 是现代网页布局中非常实用的技术:

  • 相对定位固定定位的结合体
  • 需要设置至少一个方向的阈值(top/right/bottom/left)
  • 滚动超过阈值前:按照正常文档流布局(相对定位)
  • 滚动超过阈值后:固定在当前位置(固定定位)
  • 不需要父元素设置任何定位
  • 父元素设置 overflow 会导致失效
  • 现代浏览器支持良好,IE 不支持
  • 常用于吸顶导航、表头固定、侧边栏固定、分段标题固定

CSS position 属性 CSS position 属性