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

仅在垂直内容溢出时启用Sticky导航栏的问题与解决方案

WhatsApp风格导航栏滚动条自适应解决方案

问题场景

开发WhatsApp风格导航栏时,sticky导航功能正常,但存在一个问题:即使内容较少的页面,浏览器滚动条仍会显示。原因是内容容器的高度由内部最长的section(比如示例里的PAGE 5)决定,导致所有页面都强制出现滚动条。需求是:

  • 短内容页面:隐藏滚动条,不启用滚动逻辑
  • 长内容页面:显示滚动条,保留sticky导航功能

解决方案思路

通过CSS调整基础布局,配合JavaScript动态判断内容高度来控制滚动状态:

  1. CSS调整:设置body初始overflow: hidden,section使用min-content和min-height适配内容高度,避免容器被最长section拉伸
  2. JavaScript逻辑:监听导航项点击事件,判断当前激活section的高度,动态设置body的overflowY属性

原问题代码

JavaScript

let navItems = document.querySelectorAll(".nav-item");

// 添加CSS变量记录导航项数量
document.body.style.setProperty("--total-nav-items", `${navItems.length}`);

navItems.forEach((item, index) => {
  item.addEventListener("click", () => {
    // 修改CSS变量控制导航指示器位置
    document.body.style.setProperty("--index", `${index}`);
    toogleActive();

    function toogleActive() {
      // 移除所有导航项的active类
      navItems.forEach((itemWithClass) => {
        itemWithClass.classList.remove("active");
      });

      // 给当前点击的导航项添加active类
      item.classList.add("active");
    }
  });
});

CSS

@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@500&display=swap");
:root {
  --nav-height: 3rem;
  --nav-bg: rgb(0, 128, 105);
  --text-color: white;
  --anim-speed: 0.5s;
  color-scheme: light dark;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

header {
  background-color: var(--nav-bg);
  height: var(--nav-height);
  display: grid;
  place-items: center start;
}

nav {
  display: flex;
  height: var(--nav-height);
  background-color: var(--nav-bg);
  color: var(--text-color);
  text-transform: uppercase;
  font-family: poppins;
  user-select: none;
  position: sticky;
  top: 0;
  width: 100vw;
}

nav .nav-item {
  flex: 1;
  display: grid;
  place-items: center;
  opacity: 0.5;
  transition: opacity var(--anim-speed);
}

nav .nav-item:active {
  background-color: rgba(255, 255, 255, 0.2);
}

nav .nav-item.active {
  opacity: 1;
}

nav::before {
  --indicator-width: calc(100% / var(--total-nav-items));
  content: "";
  position: absolute;
  height: 0.2rem;
  width: var(--indicator-width);
  background-color: var(--text-color);
  bottom: 0;
  left: calc(var(--index, 0) * var(--indicator-width));
  transition: left var(--anim-speed);
  box-shadow: 0 0 0.5rem rgba(0, 0, 0, 0.5);
}

#container {
  position: relative;
  z-index: -1;
  left: calc(-1 * (var(--index, 0) * 100vw));
  transition: left var(--anim-speed);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100vw;
}

#container>* {
  height: calc(100vh - var(--nav-height));
  padding: 0 1rem;
}

@media (prefers-color-scheme: dark) {
   :root {
    --nav-bg: rgb(31, 44, 52);
    --text-color: rgb(9, 148, 115);
  }
}

修复后代码

JavaScript

let navItems = document.querySelectorAll(".nav-item");
let sections = document.querySelectorAll("#container > *");

// 添加CSS变量记录导航项数量
document.body.style.setProperty("--total-nav-items", `${navItems.length}`);

navItems.forEach((item, index) => {
  item.addEventListener("click", () => {
    // 修改CSS变量控制导航指示器位置
    document.body.style.setProperty("--index", `${index}`);
    toogleActive();
    disactivateScroll();

    function toogleActive() {
      // 移除所有导航项的active类
      navItems.forEach((itemWithClass) => {
        itemWithClass.classList.remove("active");
      });

      // 给当前点击的导航项添加active类
      item.classList.add("active");
    }

    function disactivateScroll() {
      let navHeight = document.querySelector("nav").offsetHeight;
      // 计算页面最小可用高度(减去导航栏的两倍高度)
      let minHeightSection = window.innerHeight - (navHeight * 2);

      // 判断当前section高度是否超过最小可用高度,动态设置滚动状态
      if (sections[index].offsetHeight > minHeightSection) {
        document.body.style.overflowY = "auto";
      } else {
        document.body.style.overflowY = "hidden";
      }
    }

  });
});

CSS

@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@500&display=swap");
:root {
  --nav-height: 3rem;
  --nav-bg: rgb(0, 128, 105);
  --text-color: white;
  --anim-speed: 0.5s;
  color-scheme: light dark;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  overflow: hidden;
}

header {
  background-color: var(--nav-bg);
  height: var(--nav-height);
  display: grid;
  place-items: center start;
}

nav {
  display: flex;
  height: var(--nav-height);
  background-color: var(--nav-bg);
  color: var(--text-color);
  text-transform: uppercase;
  font-family: poppins;
  user-select: none;
  position: sticky;
  top: 0;
  width: 100vw;
}

nav .nav-item {
  flex: 1;
  display: grid;
  place-items: center;
  opacity: 0.5;
  transition: opacity var(--anim-speed);
}

nav .nav-item:active {
  background-color: rgba(255, 255, 255, 0.2);
}

nav .nav-item.active {
  opacity: 1;
}

nav::before {
  --indicator-width: calc(100% / var(--total-nav-items));
  content: "";
  position: absolute;
  height: 0.2rem;
  width: var(--indicator-width);
  background-color: var(--text-color);
  bottom: 0;
  left: calc(var(--index, 0) * var(--indicator-width));
  transition: left var(--anim-speed);
  box-shadow: 0 0 0.5rem rgba(0, 0, 0, 0.5);
}

#container {
  position: relative;
  z-index: -1;
  left: calc(-1 * (var(--index, 0) * 100vw));
  transition: left var(--anim-speed);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100vw;
}

#container>* {
  height: min-content;
  min-height: calc(100vh - (var(--nav-height) * 2));
  padding: 0 1rem;
  border: 5px solid red;
}

@media (prefers-color-scheme: dark) {
   :root {
    --nav-bg: rgb(31, 44, 52);
    --text-color: rgb(9, 148, 115);
  }
}

内容的提问来源于stack exchange,提问作者user19485937

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 23:33:22