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

嵌套ul导航菜单展开时最后一个li元素无法显示在菜单底部

问题根源
  • 一级子菜单.sub-1设置了overflow: visible,展开时写死的55.5px固定高度仅够容纳3个一级子项,嵌套的二级子菜单.sub-2展开后超出父容器的内容直接溢出、不占据正常文档流位置,必然会覆盖下方的最后一个列表项。
  • 主菜单显隐逻辑写反:.visible类配置的是visibility: hidden,且初始样式里visibility: 0是无效属性,visibility属性不接受数值参数。
  • 写死固定高度的展开逻辑完全没考虑嵌套子菜单展开的高度增量,只要嵌套层级展开就会出现内容溢出错位。
修复方案

1. 替换错误CSS样式

把原有CSS替换为以下内容,核心是统一子菜单溢出隐藏规则、修正显隐逻辑、给菜单项加统一内边距保证高度计算准确:

* {
    box-sizing: border-box;
}
body {
    height: 100vh;
    padding: 0;
    margin: 0;
}

nav {
    height: 10vh;
    background-color: aquamarine;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    position: relative;
}

#btn {
    position: absolute;
    top: 0;
    right: 10px;
    height: 10vh;
    display: flex;
    align-items: center;
    text-decoration: none;
}
.main {
    display: flex;
    position: absolute;
    flex-direction: column;
    list-style-type: none;
    padding-left: 0;
    align-items: center;
    top: 10vh;
    margin: 0;
    width: 100%;
    background: #fff;
    visibility: hidden;
}

.sub-1, .sub-2 {
    height: 0;
    list-style-type: none;
    padding-left: 0;
    display: flex;
    flex-direction: column;
    position: relative;
    overflow: hidden;
    visibility: hidden;
    transition: height 0.3s ease-out;
    align-items: center;
}

.height {
    visibility: visible;
    transition: height 0.3s ease;
}

.main.visible {
    visibility: visible;
}

li a {
    display: block;
    padding: 1rem 0;
}

2. 替换原有JS逻辑

去掉写死高度的写法,改为自动计算子菜单实际高度,同时处理嵌套展开时父级菜单的高度联动,保证父容器能被子内容完全撑开:

const mainMenu = document.querySelector('.main');
const subMenu1 = document.querySelector('.sub-1');
const subMenu2 = document.querySelector('.sub-2');

document.querySelector('#btn').addEventListener('click', () => {
    mainMenu.classList.toggle('visible');
    // 关闭主菜单时收起所有子菜单
    subMenu1.classList.remove('height');
    subMenu2.classList.remove('height');
    subMenu1.style.height = '';
    subMenu2.style.height = '';
})

document.querySelector('#submen-1').addEventListener('click', (e) => {
    e.stopPropagation();
    const isOpen = subMenu1.classList.contains('height');
    // 切换一级子菜单时先收起二级子菜单
    subMenu2.classList.remove('height');
    subMenu2.style.height = '';
    
    if(isOpen) {
        subMenu1.style.height = `${subMenu1.scrollHeight}px`;
        requestAnimationFrame(() => {
            subMenu1.style.height = '0px';
        })
        subMenu1.classList.remove('height');
    } else {
        subMenu1.classList.add('height');
        subMenu1.style.height = `${subMenu1.scrollHeight}px`;
        subMenu1.addEventListener('transitionend', () => {
            subMenu1.style.height = 'auto';
        }, {once: true})
    }
})

document.querySelector('#submen-2').addEventListener('click', (e) => {
    e.stopPropagation();
    const isOpen = subMenu2.classList.contains('height');
    // 切换二级子菜单前先锁定父级菜单当前高度,保证过渡效果正常
    if(subMenu1.style.height === 'auto') {
        subMenu1.style.height = `${subMenu1.scrollHeight}px`;
    }

    if(isOpen) {
        subMenu2.style.height = `${subMenu2.scrollHeight}px`;
        requestAnimationFrame(() => {
            subMenu2.style.height = '0px';
        })
        subMenu2.classList.remove('height');
    } else {
        subMenu2.classList.add('height');
        subMenu2.style.height = `${subMenu2.scrollHeight}px`;
    }

    // 过渡完成后更新父级菜单高度,自动撑开位置
    setTimeout(() => {
        subMenu1.style.height = 'auto';
        subMenu1.style.height = `${subMenu1.scrollHeight}px`;
    }, 300)
})

3. HTML结构无需修改

原有HTML的标签层级完全符合要求,不需要调整。

修复后所有子菜单展开时会自动撑开父容器高度,最后一个一级菜单项会随嵌套菜单的展开自动下移,不会被覆盖,同时保留平滑的展开收起过渡效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 10:57:19