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

小设备点击Hamburger/Toggle图标无响应问题求助

问题:小屏设备点击汉堡图标后导航菜单无法正常显示

开发网站导航菜单时遇到问题:在小屏设备上点击汉堡图标,预期的导航链接没有正常显示。已经检查过HTML、CSS和JavaScript代码,但没找到问题根源。

背景信息

  • 使用带toggle-button类的切换按钮,通过三个<span>元素构建汉堡图标
  • 导航菜单包裹在nav-menu类的<div>中,包含Home、About Me、Timeline、My Blogs、Contact Me等导航项

现有代码

HTML

<div class="toggle-button" id="toggleBtn">
  <span></span>
  <span></span>
  <span></span>
</div>

<nav class="navigation">
  <div class="nav-container">
    <div class="logo">
      <img src="https://via.placeholder.com/70" alt="Logo">
    </div>

    <div class="theme-btn">
      <i class="fas fa-sun"></i>
    </div>
    <div class="nav-menu">
      <div class="nav-item">
        <a href="home.html" class="nav-link active-btn" data-id="home">Home</a>
      </div>
      <div class="nav-item">
        <a href="about.html" class="nav-link" data-id="about">About Me</a>
      </div>
      <div class="nav-item">
        <a href="timeline.html" class="nav-link" data-id="timeline">Timeline</a>
      </div>
      <div class="nav-item">
        <a href="blog.html" class="nav-link" data-id="blog">My Blogs</a>
      </div>
      <div class="nav-item">
        <a href="contact.html" class="nav-link" data-id="contact">Contact Me</a>
      </div>
    </div>
  </div>
</nav>

CSS

.toggle-button {
  display: none;
}

.toggle-button span {
  display: block;
  width: 30px;
  height: 3px;
  margin: 6px auto;
  background-color: #008000;
  transition: background-color 0.3s ease-in-out, transform 0.3s ease-in-out;
}

@media only screen and (max-width: 767px) {
  .nav-menu {
    display: none;
  }
  .toggle-button {
    display: block;
    cursor: pointer;
    position: absolute;
    top: 1rem;
    left: 1rem;
    z-index: 1000;
  }
  .toggle-button.active span:nth-child(1) {
    transform: rotate(-45deg) translate(-5px, 6px);
  }
  .toggle-button.active span:nth-child(2) {
    opacity: 0;
  }
  .toggle-button.active span:nth-child(3) {
    transform: rotate(45deg) translate(-5px, -6px);
  }
  .toggle-button.active+.nav-menu {
    display: flex;
    flex-direction: column;
    background-color: #1a1a1a;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    justify-content: center;
    align-items: center;
    padding: 2rem;
    z-index: 999;
    opacity: 1;
    transform: translateY(0);
  }
  .nav-container {
    align-items: center;
  }
  .nav-menu {
    display: flex;
    flex-direction: column;
    gap: 1rem;
  }
  .nav-item {
    margin-right: 0;
    margin-bottom: 0.5rem;
  }
  .close-button {
    display: none;
  }
  .close-button span {
    display: block;
    width: 30px;
    height: 3px;
    background-color: #ffffff;
    transition: background-color 0.3s ease-in-out, transform 0.3s ease-in-out;
  }
  .toggle-button.active~.close-button {
    display: block;
    cursor: pointer;
    position: absolute;
    top: 1rem;
    left: 1rem;
    z-index: 1000;
  }
  .toggle-button.active~.close-button span:nth-child(1) {
    transform: rotate(45deg);
  }
  .toggle-button.active~.close-button span:nth-child(2) {
    opacity: 0;
  }
  .toggle-button.active~.close-button span:nth-child(3) {
    transform: rotate(-45deg);
  }
  .toggle-button.active~.nav-menu .nav-link {
    display: block;
  }
}

@media only screen and (max-width: 768px) {
  .navigation.active {
    background-color: #1a1a1a;
  }
  .nav-menu {
    display: flex;
    flex-direction: column;
    background-color: #1a1a1a;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    justify-content: center;
    align-items: center;
    padding: 2rem;
    z-index: 999;
    opacity: 0;
    transform: translateY(-100%);
    transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
  }
  .navigation.active .nav-menu {
    opacity: 1;
    transform: translateY(0);
  }
  .nav-item {
    margin-right: 0;
    margin-bottom: 0.5rem;
  }
}

JavaScript

const toggleButton = document.querySelector('.toggle-button');
const navMenu = document.querySelector('.nav-menu');
const closeIcon = document.querySelector('.close-button');

toggleButton.addEventListener('click', () => {
  toggleButton.classList.toggle('active');
  navMenu.classList.toggle('active');

  if (toggleButton.classList.contains('active')) {
    const buttonRect = toggleButton.getBoundingClientRect();
    navMenu.style.top = buttonRect.top + buttonRect.height + 'px';
    navMenu.style.left = buttonRect.left + 'px';
  }
});

closeIcon.addEventListener('click', () => {
  toggleButton.classList.remove('active');
  navMenu.classList.remove('active');
  toggleButton.innerHTML = '<span></span><span></span><span></span>';
});

window.addEventListener('click', function(event) {
  if (!navMenu.contains(event.target) && event.target !== toggleButton && navMenu.classList.contains('active')) {
    navMenu.classList.remove('active');
    toggleButton.classList.remove('active');
    toggleButton.innerHTML = '<span></span><span></span><span></span>';
  }
});

const navLinks = document.querySelectorAll(".nav-link");

navLinks.forEach(function(link) {
  link.addEventListener("click", function(e) {
    e.preventDefault();
    const target = link.getAttribute("data-id");

    navLinks.forEach(function(navLink) {
      navLink.classList.remove("active-btn");
    });
    link.classList.add("active-btn");

    const section = document.getElementById(target);
    if (section) {
      section.scrollIntoView({
        behavior: "smooth"
      });
    }

    if (window.innerWidth <= 767) {
      navMenu.classList.remove('active');
    }
  });
});

问题根源分析

  1. CSS选择器无效:在max-width:767px媒体查询中,使用了.toggle-button.active+.nav-menu相邻兄弟选择器,但HTML中.toggle-button和.nav-menu并不相邻(中间隔了<nav>容器),导致该样式完全不生效,菜单无法显示。
  2. 媒体查询冲突:同时存在max-width:767px和max-width:768px两个范围重叠的媒体查询,后者会覆盖前者中.nav-menu的初始样式,而JS逻辑并未触发.navigation.active类,进一步导致菜单无法正常显示。
  3. JS与CSS逻辑脱节:JS为navMenu添加active类,但CSS中没有对应.nav-menu.active的显示规则,依赖无效的兄弟选择器,导致类切换无法触发菜单显示。

修复方案

修改后的CSS

.toggle-button {
  display: none;
}

.toggle-button span {
  display: block;
  width: 30px;
  height: 3px;
  margin: 6px auto;
  background-color: #008000;
  transition: background-color 0.3s ease-in-out, transform 0.3s ease-in-out;
}

/* 统一使用768px作为小屏断点,避免冲突 */
@media only screen and (max-width: 768px) {
  .nav-menu {
    display: none;
    flex-direction: column;
    background-color: #1a1a1a;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    justify-content: center;
    align-items: center;
    padding: 2rem;
    z-index: 999;
    gap: 1rem;
  }

  /* 用active类控制菜单显示 */
  .nav-menu.active {
    display: flex;
  }

  .toggle-button {
    display: block;
    cursor: pointer;
    position: absolute;
    top: 1rem;
    left: 1rem;
    z-index: 1000;
  }

  .toggle-button.active span:nth-child(1) {
    transform: rotate(-45deg) translate(-5px, 6px);
  }

  .toggle-button.active span:nth-child(2) {
    opacity: 0;
  }

  .toggle-button.active span:nth-child(3) {
    transform: rotate(45deg) translate(-5px, -6px);
  }

  .nav-container {
    align-items: center;
  }

  .nav-item {
    margin-right: 0;
    margin-bottom: 0.5rem;
  }

  .close-button {
    display: none;
    cursor: pointer;
    position: absolute;
    top: 1rem;
    left: 1rem;
    z-index: 1000;
  }

  .close-button span {
    display: block;
    width: 30px;
    height: 3px;
    background-color: #ffffff;
    transition: background-color 0.3s ease-in-out, transform 0.3s ease-in-out;
  }

  .close-button.active span:nth-child(1) {
    transform: rotate(45deg);
  }

  .close-button.active span:nth-child(2) {
    opacity: 0;
  }

  .close-button.active span:nth-child(3) {
    transform: rotate(-45deg);
  }
}

修改后的JavaScript

const toggleButton = document.querySelector('.toggle-button');
const navMenu = document.querySelector('.nav-menu');
const closeIcon = document.querySelector('.close-button');

toggleButton.addEventListener('click', () => {
  toggleButton.classList.toggle('active');
  navMenu.classList.toggle('active');
  // 移除无效的定位设置,改用CSS固定定位
  if (closeIcon) {
    closeIcon.classList.toggle('active');
  }
});

if (closeIcon) {
  closeIcon.addEventListener('click', () => {
    toggleButton.classList.remove('active');
    navMenu.classList.remove('active');
    closeIcon.classList.remove('active');
  });
}

window.addEventListener('click', function(event) {
  if (!navMenu.contains(event.target) && event.target !== toggleButton && navMenu.classList.contains('active')) {
    navMenu.classList.remove('active');
    toggleButton.classList.remove('active');
    if (closeIcon) closeIcon.classList.remove('active');
  }
});

const navLinks = document.querySelectorAll(".nav-link");

navLinks.forEach(function(link) {
  link.addEventListener("click", function(e) {
    e.preventDefault();
    const target = link.getAttribute("data-id");

    navLinks.forEach(function(navLink) {
      navLink.classList.remove("active-btn");
    });
    link.classList.add("active-btn");

    const section = document.getElementById(target);
    if (section) {
      section.scrollIntoView({
        behavior: "smooth"
      });
    }

    if (window.innerWidth <= 768) {
      navMenu.classList.remove('active');
      toggleButton.classList.remove('active');
      if (closeIcon) closeIcon.classList.remove('active');
    }
  });
});

额外说明

  • 移除了无效的相邻兄弟选择器,改用.nav-menu.active直接控制菜单显示,确保JS类切换能触发样式变化
  • 合并了重叠的媒体查询,统一使用max-width:768px作为小屏断点,避免样式冲突
  • 简化了JS中的定位逻辑,菜单通过CSS固定定位全屏显示,无需动态计算位置
  • 优化了关闭按钮的逻辑,确保状态同步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 08:54:50