CSS 使用 position: sticky 属性实现粘性定位(附完整代码示例)

  • 原创
  • 作者:程序员三丰
  • 发布时间:2024-12-25 23:11
  • 浏览量:407
日常前端开发中经常会遇到页面导航滚动吸附,长表格表头冻结等,往往我们都会借助一些组件轮子来实现,其实通过 CSS 的属性 position: sticky 就可以简单实现。

什么是 position: sticky

在CSS中,position: sticky 是一种用于创建粘性布局的属性,它使得元素在页面滚动时可以在特定条件下保持可见。这种定位方式结合了相对定位(relative)和固定定位(fixed)的特点,在页面滚动到一定位置之前,元素按照正常文档流的位置显示;一旦页面滚动超过了设定的阈值,元素就会固定在视口中的某个位置,直到再次滚动回阈值以内。

MDN资源链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/position
元素根据正常文档流进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor)和 containing block(最近块级祖先 nearest block-level ancestor),包括 table-related 元素,基于 top、right、bottom 和 left 的值进行偏移。偏移值不会影响任何其他元素的位置。 该值总是创建一个新的层叠上下文(stacking context)。注意,一个 sticky 元素会“固定”在离它最近的一个拥有“滚动机制”的祖先上(当该祖先的 overflow 是 hidden、scroll、auto 或 overlay 时),即便这个祖先不是最近的真实可滚动祖先。这有效地抑制了任何“sticky”行为)。

粘性布局的工作原理

为了实现一个有效的粘性布局,你需要确保满足以下条件:

  • 指定阈值:必须为 sticky 元素指定 top, right, bottom, 或 left 中的一个或多个阈值,以定义何时开始应用粘性行为。例如,top: 0 表示当页面向上滚动且元素顶部距离视口顶部的距离小于等于0像素时,该元素将变为固定定位。
  • 父容器的高度:粘性元素需要有一个足够高的祖先容器,这样可以产生足够的滚动空间来触发粘性效果。如果祖先容器太小而无法滚动,则 sticky 元素将表现得像相对定位一样。
  • 溢出属性:如果 sticky 元素的任何父级元素设置了 overflow: hidden, scroll, auto, 或者 overlay 属性,并且这个父级元素是可以滚动的,那么 sticky 元素将会相对于这个父级元素而不是整个页面进行定位。

示例:导航顶部吸附

这是最常见的一种使用场景。当页面向下滚动时,导航栏可以粘贴在屏幕顶部,方便用户始终可以看到导航,快速跳转到不同页面,从而提高用户体验。

下面是一个简单的示例:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>页面标题</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <style>
            * {
                margin: 0;
                padding: 0;
                font-family: "Source Sans Pro", -apple-system,
                    BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
                    Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
                    "Segoe UI Symbol";
                font-size: 1rem;
                font-weight: 400;
                line-height: 1.5;
                color: #212529;
                text-align: left;
            }

            .nav {
                padding: 0 2rem;
                background-color: #007bff;
                color: #fff;
                height: 36px;
                line-height: 36px;
                text-align: center;
                position: sticky;
                top: 0px;
                display: flex;
                align-items: center;
            }

            .nav ul {
                list-style: none;
                display: flex;
                align-items: center;
                gap: 20px;
            }

            .nav ul li a {
                color: #fff;
                text-decoration: none;
            }

            .nav ul li a:hover {
                text-decoration: underline;
            }

            .article-list {
                padding: 20px;
            }

            .article-list div {
                padding: 10px 14px;
                border-radius: 0.2rem;
                box-shadow: inset 0 -0.1rem 0 rgba(0, 0, 0, 0.25);
                margin-bottom: 10px;
            }
        </style>
    </head>

    <body>
        <div class="nav">
            <ul>
                <li><a href="#">首页</a></li>
                <li><a href="#">文章</a></li>
                <li><a href="#">照片</a></li>
                <li><a href="#">关于我</a></li>
            </ul>
        </div>

        <div class="article-list" id="article-list"></div>

        <script>
            const $articleListContainer = document.querySelector("#article-list");
            for (let index = 1; index <= 100; index++) {
                const element = document.createElement("div");
                element.append(`${index}. 这是本站第 ${index} 篇文章。`);
                $articleListContainer.append(element);
            }
        </script>
    </body>
</html>

示例:冻结表格表头

对于长表格来说,表头可能会随着滚动而消失,这会影响用户的阅读体验。可以通过将表头设置为 sticky,可以让其在滚动过程中始终显示在视口顶部,确保用户始终能看到每一列的数据含义。

请看下面这个示例:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8" />
        <title>页面标题</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <style>
            * {
                margin: 0;
                padding: 0;
                font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont,
                    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif,
                    "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
                font-size: 1rem;
                font-weight: 400;
                line-height: 1.5;
                color: #212529;
                text-align: left;
            }

            table {
                border-collapse: collapse;
                border: 2px solid rgb(140 140 140);
                font-family: sans-serif;
                font-size: 0.8rem;
                letter-spacing: 1px;
                margin: 0 auto;
                width: 610px;
                height: 240px;
                display: block;
                overflow-x: auto;
            }

            caption {
                caption-side: center;
                padding: 10px;
                font-weight: bold;
                text-align: center;
            }

            tbody {
                white-space: nowrap;
            }

            thead,
            tfoot {
                background-color: rgb(228 240 245);
            }

            th,
            td {
                border: 1px solid rgb(160 160 160);
                padding: 8px 10px;
            }

            th {
                position: sticky;
                top: 0;
                background: #fff;
                vertical-align: bottom;
            }

            td:last-of-type {
                text-align: center;
            }

            tbody>tr:nth-of-type(even) {
                background-color: rgb(237 238 242);
            }
        </style>
    </head>

    <body>
        <table>
            <caption>
                这是一个冻结表头的长表格
            </caption>
            <colgroup>
                <col />
            </colgroup>
            <tbody>
                <tr>
                    <th>名称</th>
                    <th>HEX</th>
                    <th>HSLa</th>
                    <th>RGBa</th>
                </tr>
                <tr>
                    <td>Teal</td>
                    <td><code>#51F6F6</code></td>
                    <td><code>hsla(180, 90%, 64%, 1)</code></td>
                    <td><code>rgba(81, 246, 246, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
                <tr>
                    <td>Goldenrod</td>
                    <td><code>#F6BC57</code></td>
                    <td><code>hsla(38, 90%, 65%, 1)</code></td>
                    <td><code>rgba(246, 188, 87, 1)</code></td>
                </tr>
            </tbody>
        </table>

        <script>
        </script>
    </body>

</html>

注意事项

  • 兼容性问题:尽管现代浏览器普遍支持 position: sticky,但在一些较旧版本的浏览器中可能存在兼容性问题。因此,建议开发者检查目标用户的浏览器环境,并考虑提供适当的方案。
  • z-index 和层叠上下文:使用 position: sticky 时需要注意其他元素的 z-index 值,因为这可能会影响到哪些元素覆盖在 sticky 元素之上。
  • 性能考量:频繁地处理滚动事件可能会对性能造成影响,尤其是在移动设备上。过度使用 sticky 可能会导致页面加载速度变慢或响应时间增加。

总之,position: sticky 提供了一种简便的方法来创建交互式的用户体验,但它也有一些限制和注意事项,我们应该根据具体的应用场景合理选择是否使用以及如何优化其性能。

声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://mp.51blog.xyz/article/77.html

文章归档

推荐文章

buildadmin logo
Thinkphp8 Vue3 Element PLus TypeScript Vite Pinia

🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。

热门标签

PHP ThinkPHP ThinkPHP5.1 Go Mysql Mysql5.7 Redis Linux CentOS7 Git HTML CSS CSS3 Javascript JQuery Vue LayUI VMware Uniapp 微信小程序 docker wiki Confluence7 学习笔记 uView ES6 Ant Design Pro of Vue React ThinkPHP6.0 chrome 扩展 翻译工具 Nuxt SSR 服务端渲染 scrollreveal.js ThinkPHP8.0 Mac webman 跨域CORS vscode GitHub ECharts Canvas