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

横向导航栏滑块在非开发页面无法正常初始化及滑动的问题排查求助

横向导航栏滑块在非开发页面无法正常初始化及滑动的问题排查求助

大家好,我最近在做一个带顶部居中横向导航栏的HTML页面,想要实现一个滑动选择条的效果——不是给选中或者hover的导航项单独加边框,而是让一个滑块在各个导航项之间平滑滑动切换。目前开发页面(page-development)的效果是正常的:比如鼠标hover到"the cabaret"时,滑块会从"development"的位置平滑滑过去,中途状态也符合预期:

开发页面滑块正常滑动的中途状态

但其他页面(比如messagetomountains、cabaret页面)的滑块完全不正常——页面加载后滑块变成导航栏中间的一条竖线,而且hover其他导航项也完全没反应:

非开发页面滑块异常状态

我已经用console.log确认了切换页面时activeLink参数是正确传递的,但滑块就是不工作,这问题已经卡了我好几个小时了。

下面是我认为相关的HTML、CSS和JS代码:

HTML代码

<div id="page-development" style="display: none;"> 
      <nav class="navbar">
        <div class ="slider"></div>
        <a href="#development" class="active" id = "development-link">development</a>
        <a href="#messagetomountains">messagetomountains</a>
        <a href="#cabaret">the cabaret</a>
      </nav> 
      <h2>dev page</h2>
      <p>this is the development page.</p>
    </div>
  
    <div id="page-messagetomountains" style="display: none;">
      <nav class="navbar">
        <div class ="slider"></div>
        <a href="#development">development</a>
        <a href="#messagetomountains" class="active" id = "messagetomountains-link">messagetomountains</a>
        <a href="#cabaret">the cabaret</a>
      </nav> 
      <h2>messagetomountains page</h2>
      <p>this is the messagetomountains page.</p>
    </div>
  
    <div id="page-cabaret" style="display: none;">
      <nav class="navbar">
        <div class ="slider"></div>
        <a href="#development">development</a>
        <a href="#messagetomountains">messagetomountains</a>
        <a href="#cabaret" class="active" id = "cabaret-link">the cabaret</a>
      </nav>  
      <h2>cabaret page</h2>
      <p>welcome to the cabaret.</p>
    </div>

CSS代码

#page-development,
#page-messagetomountains,
#page-cabaret {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #202020;
    text-align: center;
    z-index: 10;
    opacity: 0;
    transition: opacity 1s ease-in-out; 
    text-shadow: none;
    font-family: "Lucida Console", "Courier New", monospace;
}

#page-development {
  background: radial-gradient(circle, #f4d4b4 0%, #e9ceb3 100%);
}

#page-messagetomountains {
  background: radial-gradient(circle, #94d0e8 0%, #82c1db 100%);
  color: white ;
}

#page-cabaret {
  background: radial-gradient(circle, #8E98F9 0%, #868ed6 100%);
}

.navbar {
  position: relative;
  display: flex;
  justify-content: center;
  background-color: #82c1db;
  padding: 10px 20px;
}

.navbar a {
  position: relative;
  color: white;
  text-decoration: none;
  padding: 8px 20px;
  margin: 0 150px;
  border: 2px solid transparent;
  border-radius: 20px;
  z-index: 1; /* links above slider */
  transition: color 0.3s, transform 0.3s;
}

.navbar a:hover {
  color: #eeffff;
}

.navbar a.active {
  color: #ffffff;
}

/* moving border */
.slider {
  position: absolute;
  height: calc(100% - 23px); /* try match link padding */
  border: 2px solid #ffffff;
  border-radius: 20px;
  background: none;
  transition: all 0.4s ease;
  z-index: 0; /* sits behind the links */
}

JavaScript代码

// Add event listeners for option clicks
const options = document.querySelectorAll('.option');
let selectedOption = null;

options.forEach((option) => {
  option.addEventListener('click', () => {
    // Deselect previous option
    if (selectedOption) {
      selectedOption.classList.remove('selected');
    }

    // Select the clicked option
    option.classList.add('selected');
    selectedOption = option;

    // Get page ID from data attribute in HTML
    const pageId = option.getAttribute('data-page');
    const activeLinkId = option.getAttribute('data-active-link');
    const activeLink = document.getElementById(activeLinkId);
    navigateToPage(pageId, activeLink);
  });
});

// PAGE NAVIGATION
function navigateToPage(pageId, activeLink) {
  const portfolioPageContent = document.getElementById('portfolio-page').children; // children so not background, goal to swipe text elements up
  const selectedPage = document.getElementById(pageId);

  if (!selectedPage) {
    console.error(`Page with ID "${pageId}" not found.`);
    return;
  }


  // Update navbar links for active state
  const links = document.querySelectorAll('.navbar a');
  links.forEach(link => link.classList.remove('active'));  // Remove 'active' from all links
  if (activeLink) {
    activeLink.classList.add('active');  // Add 'active' to the selected link
    moveSlider(activeLink); // Move slider to active link
  }


  // Swipe the portfolio page content up, not the background
  gsap.to(portfolioPageContent, {
    y: '-200%',
    opacity: 0,
    duration: 0.8,
    ease: 'power2.inOut',
    onComplete: () => {

      if (selectedPage) {
        selectedPage.style.display = 'block';
        gsap.to(selectedPage, { opacity: 1, duration: 0});
        
        
      } else {
        console.error(`Page with ID "${pageId}" not found.`);
      }

      // Fade in new page first, then hide old page
      gsap.to(selectedPage, { opacity: 1, duration: 1 }, "fade-in")
        .then(() => {
          document.getElementById('portfolio-page').style.visibility = 'hidden';
        });


        console.log(activeLink);
        if (activeLink) {
          setTimeout(() => {
            moveSlider(activeLink);
          }, 100);
        }

        // Add hover-over effect to move the slider
        links.forEach(link => {
          link.addEventListener('mouseenter', () => moveSlider(link));
        });

        // Keep slider on the active link when not hovering
        navbar.addEventListener('mouseleave', () => {
          if (activeLink) moveSlider(activeLink);
        });

    },
  });
}

const navbar = document.querySelector('.navbar');
const slider = document.querySelector('.slider');
const links = document.querySelectorAll('.navbar a');
console.log(links);

// Function to move the slider
function moveSlider(link) {
  const rect = link.getBoundingClientRect(); // Get the link's position
  const navbarRect = navbar.getBoundingClientRect(); // Get navbar's position

  const sliderWidthAdjustment = 1.5; // Shrink the width slightly
  const sliderLeftAdjustment = -1.5; // Offset to the left slightly

  slider.style.width = `${rect.width - sliderWidthAdjustment}px`; // Adjust width
  slider.style.left = `${rect.left - navbarRect.left + sliderLeftAdjustment}px`; // Adjust position

}

补充上下文

页面初始是一个中央的portfolio页面,里面有3个选项;点击选项后,会把portfolio页面的文字内容向上滑出隐藏,然后淡入对应的子页面(比如development、cabaret)。只有development页面的滑块正常工作,另外两个页面的滑块完全无法初始化和滑动。

我尝试过的方法

  • 重写moveSlider函数,调整滑块的计算逻辑,但不管怎么改,只有开发页面能用;
  • 尝试在navigateToPage函数里重新初始化导航栏相关逻辑,同样没有效果;
  • 为了排查新增了activeLink参数,导致现在代码有点混乱,但确认参数传递是正确的。

这是我第一次使用GSAP,也是第一次做这种页面内淡入淡出切换(不是直接跳转到/development这种路径),感觉自己把页面切换逻辑搞复杂了,才导致滑块出问题。真心希望能得到大家的指导,帮我找出问题所在,修复滑块在非开发页面的初始化和滑动功能!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 15:08:05