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

如何解决响应式Navbar移动端下拉菜单导致按钮移位问题

修复移动端导航栏按钮移位问题

问题核心是下拉菜单与按钮处于同一文档流,展开时会挤压按钮位置。通过绝对定位让菜单脱离文档流,即可实现菜单在按钮下方展开且按钮不移位。

修改后的关键代码片段

<div className="relative"> {/* 添加relative作为菜单绝对定位的参照容器 */}
  <button type='button' onClick={() => setIsOpen(!isOpen)} className='sm:hidden inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white'>
    <span className='sr-only'>Open main menu</span>
    {isOpen ? (
      <XMarkIcon className="block h-6 w-6 " aria-hidden="true" />
    ) : (
      <Bars3Icon className="block h-6 w-6" aria-hidden="true" />
    )}
  </button>
  {isOpen && (
    {/* 用绝对定位让菜单脱离文档流,在按钮下方靠右展开 */}
    <div className='absolute right-0 top-full mt-2 space-y-1 px-2 pb-3 pt-2 w-48 bg-gray-800 rounded-md'>
      <div className='rounded-md ring-1 ring-black ring-opacity-5 overflow-hidden'>
        {menu_list.map((item) => (
          <Link href={item.href} key={item.name} className={classNames(
                item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white',
                'block px-4 py-2 text-sm'
              )}
              aria-current={item.current ? 'page' : undefined}
            >
              {item.name}
          </Link>
        ))}
      </div>
    </div>
  )}
</div>

完整修改后的Navbar2.jsx代码

'use client';

import Link from 'next/link';
import Image from 'next/image';
import NavItem from './NavItem';
import { motion } from 'framer-motion';
import { navVariants } from '../utils/motion';
import styles from '../styles';
import { useState } from 'react';
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline';
import { Disclosure, Menu, Transition } from '@headlessui/react';

const menu_list = [
  { name: 'Home', href: '/', current: true },
  { name: 'About', href: '/', current: false },
  { name: 'Contact', href: '/', current: false },
]

function classNames(...classes) {
  return classes.filter(Boolean).join(' ')
}

const Navbar2 = () => {
  const [isOpen, setIsOpen] = useState(false);

  return(
    <motion.nav
      variants={navVariants}
      initial='hidden'
      whileInView='show'
      className={`${styles.xPaddings} py-8 relative z-30`}
    >
      <div className='absolute w-[50%] inset-0 gradient-01' />
      <div className={`${styles.innerWidth} mx-auto flex justify-between gap-8`}>
        <Link href='/' className='z-30 opacity-50 hover:opacity-100'>
          <Image
            src='/headset.svg'
            alt='logo'
            width={30}
            height={30}
            className='object-contain'
          />
        </Link>
        <h2 className='font-extrabold text-[24px] leading-[30px] text-white'>
          TITLE
        </h2>
        <div className='hidden sm:flex space-x-4'>
          {menu_list.map((item) => (
            <Link href={item.href} className={classNames(
              item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white',
              'rounded-md px-3 py-2 text-sm font-medium'
            )}
            aria-current={item.current ? 'page' : undefined}
            >
              {item.name}
            </Link>
          ))}
        </div>
      <div className="relative">
          <button type='button' onClick={() => setIsOpen(!isOpen)} className='sm:hidden inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white'>
            <span className='sr-only'>Open main menu</span>
            {isOpen ? (
              <XMarkIcon className="block h-6 w-6 " aria-hidden="true" />
            ) : (
              <Bars3Icon className="block h-6 w-6" aria-hidden="true" />
            )}
          </button>
          {isOpen && (
            <div className='absolute right-0 top-full mt-2 space-y-1 px-2 pb-3 pt-2 w-48 bg-gray-800 rounded-md'>
              <div className='rounded-md ring-1 ring-black ring-opacity-5 overflow-hidden'>
                {menu_list.map((item) => (
                  <Link href={item.href} key={item.name} className={classNames(
                        item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white',
                        'block px-4 py-2 text-sm'
                      )}
                      aria-current={item.current ? 'page' : undefined}
                    >
                      {item.name}
                  </Link>
                ))}
              </div>
            </div>
          )}
        </div>
      </div>
    </motion.nav>
  )
}

export default Navbar2;

修改说明

  • relative:给按钮外层容器添加相对定位,让内部绝对定位的菜单以此为参照点
  • absolute right-0 top-full mt-2:让菜单脱离文档流,靠右对齐按钮底部并保留小间距,彻底避免挤压按钮
  • w-48 bg-gray-800:固定菜单宽度并添加背景,提升移动端菜单的可读性和美观度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 01:17:53