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

滚动时固定右侧菜单底部并实现标签内容滚动

我来帮你搞定这个需求!你要实现的是滚动时右侧菜单固定,固定状态下标签内容能滚动且底部对齐视窗,当页面滚到足够底部时菜单底部对齐父容器。下面是调整后的完整代码和详细解释:

解决方案

核心思路拆解

  • 第一步:监听页面滚动,判断菜单何时需要从默认状态切换到固定状态。
  • 第二步:菜单固定时,动态计算标签内容区域的高度,让它刚好填满导航栏下方到视窗底部的空间,实现内容滚动。
  • 第三步:当页面滚动到菜单底部即将碰到父容器底部时,切换菜单的固定方式,让它贴在父容器底部,避免遮挡下方的按钮。

修改后的JavaScript代码

window.addEventListener("scroll", handleScroll);

function handleScroll() {
  const $panel = $(".menu")[0];
  const $navbar = $(".navbar");
  const navbarHeight = $navbar.outerHeight();
  const windowHeight = $(window).height();
  const $wrapper = $("#wrapper");
  const wrapperOffsetTop = $wrapper.offset().top;
  const wrapperTotalHeight = $wrapper.outerHeight();
  const wrapperBottom = wrapperOffsetTop + wrapperTotalHeight;
  const panelTotalHeight = $panel.offsetHeight;
  const tabNavHeight = $panel.querySelector(".nav-tabs").offsetHeight;

  // 菜单触发固定的滚动阈值(导航栏底部刚好碰到菜单顶部时的滚动距离)
  const stickThreshold = wrapperOffsetTop - navbarHeight;
  // 菜单触发底部对齐父容器的阈值(视窗顶部滚动到父容器底部上方一个视窗高度时)
  const bottomStickThreshold = wrapperBottom - windowHeight;

  if ($(this).scrollTop() > stickThreshold) {
    $panel.classList.add("sticky");

    // 判断是否需要切换到父容器底部对齐模式
    if ($(this).scrollTop() > bottomStickThreshold) {
      $panel.classList.add("sticky-bottom");
      // 滚动区域高度 = 菜单总高度 - 标签栏高度
      $panel.querySelector(".tab-content").style.height = `${panelTotalHeight - tabNavHeight}px`;
    } else {
      $panel.classList.remove("sticky-bottom");
      // 滚动区域高度 = 视窗高度 - 导航栏高度 - 标签栏高度
      $panel.querySelector(".tab-content").style.height = `${windowHeight - navbarHeight - tabNavHeight}px`;
    }
  } else {
    // 恢复默认状态
    $panel.classList.remove("sticky");
    $panel.classList.remove("sticky-bottom");
    $panel.querySelector(".tab-content").style.height = "";
  }
}

调整后的CSS代码

.navbar {
  background-color: #fff;
  border-bottom: 1px solid;
  font-size: 48px;
  line-height: 48px;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100; /* 确保导航栏在最上层 */
}

.contents {
  margin-top: 55px; /* 给固定导航栏留出空间 */
}

/* 菜单固定在视窗顶部时的样式 */
.menu.sticky {
  position: fixed;
  top: 55px;
  right: 0;
  width: 31.491712707182323%;
  z-index: 90; /* 低于导航栏,高于内容 */
}

/* 菜单固定在父容器底部时的样式 */
.menu.sticky.sticky-bottom {
  top: auto; /* 取消顶部固定 */
  bottom: 0; /* 固定在视窗底部,同时受父容器限制 */
}

.menu .tab-content {
  padding: 20px;
  overflow-y: auto; /* 开启垂直滚动 */
  /* 默认不设置高度,由JS动态计算 */
}

.menu button {
  margin-top: 20px;
}

.btn.pull-right {
  margin: 20px;
}

/* 给父容器设置相对定位,确保菜单底部对齐时的参考正确 */
#wrapper {
  position: relative;
}

完整HTML结构(需引入Bootstrap)

因为用到了nav-tabs和tab-pane的切换功能,需要引入Bootstrap的样式和脚本:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>

<div class="navbar navbar-fixed-top">NAVBAR</div>
<div class="contents">
  <div class="row-fluid">
    <div class="span12">
      <h3>Here is some additional stuff</h3>
      <h5>And even more</h5>
    </div>
  </div>
  <div class="row-fluid">
    <div id="wrapper">
      <div class="span8" style="border: 1px solid blue;">
        <p>Some content</p>
        <p>Some content</p>
        <p>Some content</p>
        <!-- 此处省略重复的内容p标签 -->
      </div>
      <div class="span4" style="border: 1px solid red;">
        <div class="menu" style="border: 1px solid green;">
          <ul class="nav nav-tabs">
            <li><a href="#first" data-toggle="tab">First</a></li>
            <li><a href="#second" data-toggle="tab">Second</a></li>
          </ul>
          <div class="tab-content">
            <div id="first" class="tab-pane active">
              <ul>
                <li>Item</li>
                <li>Item</li>
                <!-- 此处省略重复的列表项li标签 -->
              </ul>
            </div>
            <div id="second" class="tab-pane">Second tab contents</div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="row-fluid">
    <div class="span12">
      <button class="btn pull-right">Button I don't want hidden</button>
    </div>
  </div>
</div>

关键细节说明

  1. 动态高度计算:通过JS实时获取视窗、导航栏、标签栏的高度,确保滚动区域刚好填满可用空间,不会出现滚动条过长或过短的问题。
  2. 双固定模式切换:通过两个滚动阈值,分别控制菜单“顶部固定”和“底部对齐父容器”的切换,避免菜单遮挡页面底部的按钮。
  3. 层级管理:给导航栏和菜单设置不同的z-index,确保导航栏始终在最上层,菜单在内容之上,避免被遮挡。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:53:16