使用纯 JavaScript (最常用)

这是最核心、最直接的实现方式,理解了它,你就掌握了这个效果的精髓。

js实现网页向下滚动导航消失
(图片来源网络,侵删)

实现原理

  1. 监听滚动事件:使用 window.addEventListener('scroll', ...) 来监听用户滚动页面的行为。
  2. 获取滚动位置:在滚动事件触发时,通过 window.scrollYwindow.pageYOffset 获取当前页面垂直滚动的距离。
  3. 判断滚动方向:通过比较当前滚动位置和上一次的滚动位置,来判断用户是向上还是向下滚动。
  4. 添加/移除类:根据滚动方向和预设的阈值(比如滚动超过50px才触发),给导航栏元素添加或移除一个控制显示/隐藏的CSS类(.hide)。
  5. 优化性能:滚动事件会非常频繁地触发,所以需要使用 防抖节流 来优化性能,避免浏览器卡顿。

完整代码示例

HTML 结构

创建一个简单的导航栏和一些占位内容,以便可以滚动。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">滚动导航消失效果</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <nav id="navbar">
        <div class="logo">我的Logo</div>
        <ul>
            <li><a href="#">首页</a></li>
            <li><a href="#">lt;/a></li>
            <li><a href="#">服务</a></li>
            <li><a href="#">联系</a></li>
        </ul>
    </nav>
    <main>
        <h1>向下滚动,导航栏会消失</h1>
        <p>向上滚动,导航栏会重新出现。</p>
        <!-- 为了演示,添加很多占位内容 -->
        <div style="height: 2000px; background: linear-gradient(to bottom, #f0f0f0, #e0e0e0);">
            <p style="text-align: center; margin-top: 1000px;">滚动到这里试试看</p>
        </div>
    </main>
    <script src="script.js"></script>
</body>
</html>

CSS 样式

这里我们定义导航栏的默认样式和隐藏时的样式。

js实现网页向下滚动导航消失
(图片来源网络,侵删)
/* style.css */
body {
    margin: 0;
    font-family: sans-serif;
}
#navbar {
    position: fixed; /* 关键:固定定位 */
    top: 0;
    left: 0;
    width: 100%;
    background-color: #333;
    color: white;
    padding: 15px 0;
    text-align: center;
    z-index: 1000; /* 确保导航栏在最上层 */
    transition: top 0.3s ease-in-out; /* 关键:添加平滑过渡效果 */
}
#navbar .logo {
    float: left;
    padding: 0 20px;
    font-weight: bold;
}
#navbar ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    float: right;
}
#navbar ul li {
    display: inline;
}
#navbar ul li a {
    color: white;
    text-decoration: none;
    padding: 0 20px;
}
/* 定义隐藏状态的类 */
#navbar.hide {
    top: -60px; /* 将导航栏向上移动,完全移出视口 */
}
main {
    padding-top: 60px; /* 为内容添加内边距,避免被固定的导航栏遮挡 */
}

JavaScript 逻辑

这是实现效果的核心代码,包含了滚动方向判断和节流优化。

// script.js
document.addEventListener('DOMContentLoaded', () => {
    const navbar = document.getElementById('navbar');
    let lastScrollTop = 0; // 记录上一次的滚动位置
    // 使用节流函数来优化性能
    function throttle(func, limit) {
        let inThrottle;
        return function() {
            const args = arguments;
            const context = this;
            if (!inThrottle) {
                func.apply(context, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        }
    }
    window.addEventListener('scroll', throttle(() => {
        // 获取当前滚动位置
        const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
        // 判断滚动方向
        if (scrollTop > lastScrollTop && scrollTop > 100) {
            // 向下滚动,并且滚动超过100px
            navbar.classList.add('hide');
        } else {
            // 向上滚动
            navbar.classList.remove('hide');
        }
        // 更新上一次的滚动位置
        lastScrollTop = scrollTop;
    }, 150)); // 150ms的节流时间
});

使用 CSS (更简单,但有局限性)

如果不需要考虑滚动方向,只要滚动就隐藏,这个方法最简单。

实现原理

利用 target 伪类,我们创建一个隐藏的锚点,当页面滚动到这个锚点时,target 生效,改变导航栏的样式。

js实现网页向下滚动导航消失
(图片来源网络,侵删)

完整代码示例

HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">CSS滚动隐藏</title>
    <link rel="stylesheet" href="css-only-style.css">
</head>
<body>
    <!-- 隐藏的锚点,当页面滚动到这里时触发效果 -->
    <a id="hide-nav"></a>
    <nav id="navbar">
        <div class="logo">我的Logo</div>
        <ul>
            <li><a href="#">首页</a></li>
            <li><a href="#hide-nav">隐藏我</a></li> <!-- 点击此链接会触发效果 -->
            <li><a href="#">lt;/a></li>
            <li><a href="#">服务</a></li>
        </ul>
    </nav>
    <main>
        <h1>点击导航栏中的“隐藏我”链接</h1>
        <p>导航栏会隐藏,点击浏览器的前进/后退按钮可以恢复。</p>
        <div style="height: 2000px; background: #f5f5f5;"></div>
    </main>
</body>
</html>

CSS

/* css-only-style.css */
body {
    margin: 0;
    font-family: sans-serif;
}
#navbar {
    position: fixed;
    top: 0;
    width: 100%;
    background-color: #333;
    color: white;
    padding: 15px 0;
    text-align: center;
    transition: top 0.3s ease-in-out;
}
#navbar .logo {
    float: left;
    padding: 0 20px;
    font-weight: bold;
}
#navbar ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    float: right;
}
#navbar ul li {
    display: inline;
}
#navbar ul li a {
    color: white;
    text-decoration: none;
    padding: 0 20px;
}
/* 核心:当页面URL的target是#hide-nav时,隐藏导航栏 */
body:target #navbar {
    top: -60px;
}
main {
    padding-top: 60px;
}

局限性

  • 不智能:它只响应URL的 target 变化,而不是真实的滚动行为。
  • 交互差:用户必须点击特定链接才能触发,不符合“自然滚动”的直觉。
  • 恢复困难:通常需要用户点击浏览器的前进/后退按钮才能恢复导航栏。

使用 JavaScript 库 (如 Headroom.js)

对于追求专业效果和健壮性的项目,使用现成的库是最好的选择。

实现原理

Headroom.js 是一个专门为此效果设计的轻量级库,它封装了所有的逻辑,包括滚动方向判断、防抖、元素状态管理等,并提供了一些高级选项,如 pin(固定在顶部)和 offset(偏移量)。

完整代码示例

安装 Headroom.js 可以通过 npm 或直接使用 CDN。

HTML HTML 结构和方案一基本一样。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">Headroom.js 滚动隐藏</title>
    <link rel="stylesheet" href="headroom-style.css">
    <!-- 引入 Headroom.js -->
    <script src="https://cdn.jsdelivr.net/npm/headroom.js@0.12.0/dist/headroom.min.js"></script>
</head>
<body>
    <nav id="navbar">
        <div class="logo">Headroom.js Logo</div>
        <ul>
            <li><a href="#">首页</a></li>
            <li><a href="#">lt;/a></li>
            <li><a href="#">服务</a></li>
            <li><a href="#">联系</a></li>
        </ul>
    </nav>
    <main>
        <h1>使用 Headroom.js 实现的专业滚动效果</h1>
        <p>这个库处理了所有复杂的边缘情况,效果非常流畅。</p>
        <div style="height: 2000px; background: linear-gradient(to bottom, #4facfe, #00f2fe);">
            <p style="text-align: center; margin-top: 1000px; color: white;">滚动到这里试试看</p>
        </div>
    </main>
    <script src="headroom-script.js"></script>
</body>
</html>

CSS CSS 也和方案一类似,但 Headroom.js 会动态添加 headroom, pinned, unpinned 等类。

/* headroom-style.css */
body {
    margin: 0;
    font-family: sans-serif;
}
#navbar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    background-color: #333;
    color: white;
    padding: 15px 0;
    text-align: center;
    z-index: 1000;
    /* Headroom.js 会添加 transition 类 */
    transition: transform 0.3s ease-in-out;
}
/* Headroom.js 添加的类 */
#navbar.headroom {
    transition: transform 0.3s ease-in-out;
}
#navbar.headroom--pinned {
    /* 固定在顶部时的样式 */
    transform: translateY(0);
}
#navbar.headroom--unpinned {
    /* 从顶部消失时的样式 */
    transform: translateY(-100%);
}
#navbar .logo {
    float: left;
    padding: 0 20px;
    font-weight: bold;
}
#navbar ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    float: right;
}
#navbar ul li {
    display: inline;
}
#navbar ul li a {
    color: white;
    text-decoration: none;
    padding: 0 20px;
}
main {
    padding-top: 60px;
}

JavaScript 使用 Headroom.js 只需几行代码。

// headroom-script.js
document.addEventListener('DOMContentLoaded', () => {
    const navbar = document.querySelector("#navbar");
    // 初始化 Headroom
    const headroom  = new Headroom(navbar, {
        // 可选配置
        tolerance: 5, // 滚动多少距离才触发
        offset: 80,    // 滚动多少距离才隐藏
        // 还可以配置 'pin'、'unpin' 等事件的回调函数
    });
    // 启动
    headroom.init();
});

总结与对比

特性 方案一 (原生 JS) 方案二 (纯 CSS) 方案三 (Headroom.js)
实现复杂度 中等 非常低 非常低
灵活性 极高,可完全自定义 极低,功能受限 高,有丰富配置选项
性能 良好(需手动优化) 极佳 极佳(库已优化)
用户体验 ,符合直觉 差,交互不自然 极佳,效果专业流畅
适用场景 大多数自定义项目 简单、静态页面,或特殊需求 专业项目,追求最佳效果和健壮性

推荐选择

  • 学习或快速实现:选择 方案一,它能帮你深刻理解原理。
  • 简单静态页面:如果只是做一个简单的展示页,方案二 可以快速搞定。
  • 商业项目或追求完美:强烈推荐 方案三Headroom.js 是业界的标准解决方案,稳定可靠。