You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现多粘性区块的锚点导航功能

实现多粘性区块的锚点导航功能

嘿,我懂你碰到的麻烦了!当所有section都设置成position: sticky; top: 0之后,它们其实都堆叠在视口顶部的同一位置,传统的锚点链接自然没法正常工作——毕竟浏览器找不到每个section对应的滚动偏移量嘛。不过用JavaScript完全能解决这个问题,我来帮你调整代码,让导航圆点既能随滚动高亮,点击也能精准跳转到对应区块。

首先先修正你HTML里的一个小错误:你的.scroll-control列表里多了一个多余的</a>标签,先把它删掉,不然会影响DOM结构。

接下来是完整的实现代码,我会把HTML、CSS和JavaScript整合到一起:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sticky Sections with Dot Navigation</title>
    <style>
        body {
            margin: 0px;
            padding: 0px;
            scroll-behavior: smooth; /* 修正原语法错误:scroll: behavior smooth → scroll-behavior: smooth */
        }

        section {
            position: sticky;
            width: 100%;
            height: 100vh;
            top: 0;
            display: inline-block;
            box-sizing: border-box;
        }

        .text {
            font-size: 40px;
            font-weight: 600;
            text-align: center;
            padding-top: 20vh;
            height: 100%;
        }

        .gray {
            background-color: #5c5d5f;
        }

        .red {
            background-color: #e31426;
        }

        .scroll-control {
            position: fixed;
            right: 70px;
            top: 40%;
            transform: translateY(-50%); /* 修正居中方向:原translateX改为Y轴居中 */
            z-index: 700;
            list-style: none; /* 移除列表默认圆点 */
            padding: 0;
        }

        .scroll-control a {
            text-decoration: none; /* 移除链接下划线 */
        }

        .scroll-control a span {
            cursor: pointer;
            display: block;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            margin: 30px 0;
            transition: all 0.3s ease; /* 添加过渡动画,让样式变化更丝滑 */
        }

        .scroll-control a span:hover {
            opacity: 1;
            transform: scale(1.5);
        }

        .inactive {
            background-color: #000;
            opacity: 0.7;
        }

        .current {
            opacity: 1;
            background-color: #000;
            transform: scale(1.5);
        }
    </style>
</head>
<body>
    <ul class="scroll-control">
        <li><a href="#1"><span class="one current"></span></a></li>
        <li><a href="#2"><span class="two inactive"></span></a></li>
        <li><a href="#3"><span class="three inactive"></span></a></li>
        <li><a href="#4"><span class="four inactive"></span></a></li>
    </ul>

    <section id="1" class="panel gray">
        <div class="text">SECTION 1</div>
    </section>
    <section id="2" class="panel red">
        <div class="text">SECTION 2</div>
    </section>
    <section id="3" class="panel gray">
        <div class="text">SECTION 3</div>
    </section>
    <section id="4" class="panel red">
        <div class="text">SECTION 4</div> <!-- 修正原文本错误:SECTION 2 → SECTION 4 -->
    </section>

    <script>
        // 获取所有区块和导航圆点元素
        const sections = document.querySelectorAll('section');
        const navSpans = document.querySelectorAll('.scroll-control span');

        // 滚动监听:更新当前激活的导航圆点
        function updateNavStatus() {
            // 计算滚动位置(加上视口高度一半,用来判断哪个区块处于视口核心区域)
            const scrollPosition = window.scrollY + window.innerHeight / 2;

            sections.forEach((section, index) => {
                const sectionTop = section.offsetTop;
                const sectionBottom = sectionTop + section.offsetHeight;

                // 当滚动位置落在当前区块范围内时,标记对应导航圆点为激活状态
                if (scrollPosition >= sectionTop && scrollPosition < sectionBottom) {
                    navSpans.forEach(span => span.classList.remove('current', 'inactive'));
                    navSpans[index].classList.add('current');
                    // 给其他圆点添加非激活样式
                    navSpans.forEach((span, i) => {
                        if (i !== index) span.classList.add('inactive');
                    });
                }
            });
        }

        // 导航圆点点击事件:平滑滚动到对应区块
        navSpans.forEach((span, index) => {
            span.addEventListener('click', (e) => {
                e.preventDefault(); // 阻止默认锚点跳转行为
                // 计算目标区块的滚动位置(区块在文档中的原始顶部偏移量)
                const targetScrollTop = sections[index].offsetTop;
                // 平滑滚动到目标位置
                window.scrollTo({
                    top: targetScrollTop,
                    behavior: 'smooth'
                });
            });
        });

        // 页面初始化时执行一次,确保导航状态正确
        updateNavStatus();
        // 监听滚动事件,实时更新导航状态
        window.addEventListener('scroll', updateNavStatus);
    </script>
</body>
</html>

关键逻辑说明

  • CSS修正:调整了滚动行为的语法错误,修正了导航的居中方向,添加了过渡动画让样式变化更自然。
  • 滚动监听逻辑:通过判断滚动位置落在哪个区块的文档范围内,来高亮对应导航圆点——因为sticky区块的offsetTop是它在文档中的原始位置,滚动到这个位置时,目标区块会自动顶在视口顶部。
  • 点击导航处理:阻止默认锚点跳转,手动计算并平滑滚动到目标区块的原始位置,确保精准切换。

这样调整后,你的导航圆点就能正常工作了:滚动时自动高亮当前显示的区块,点击圆点也能平滑跳转到对应内容。

备注:内容来源于stack exchange,提问作者Marielle Nadeau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 09:19:51