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

如何通过CSS或JavaScript实现悬停菜单图标时展开子菜单

鼠标悬停图标展开子菜单的实现方案

下面提供两种实现方式:纯CSS方案(适合简单交互场景)和JavaScript方案(适合需要复杂逻辑的场景)。

纯CSS实现方案

调整后的HTML结构

先把图标单独用元素包裹,确保精准定位悬停触发区域:

<ul class="main-menu">
    <li class="menu-item">
        <span class="menu-icon">📌</span> <!-- 悬停触发的图标 -->
        <span class="menu-text">主菜单</span>
        
        <!-- 带叠加层的子菜单 -->
        <ul class="sub-menu">
            <li class="sub-item">子菜单项1</li>
            <li class="sub-item">子菜单项2</li>
        </ul>
    </li>
</ul>

CSS样式代码

通过相邻兄弟选择器监听图标悬停事件,添加过渡动画优化交互体验,叠加层用伪元素实现:

/* 基础样式重置 */
ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.main-menu .menu-item {
    position: relative;
    display: inline-block;
    padding: 8px 12px;
    cursor: pointer;
}

/* 子菜单默认隐藏,设置过渡效果 */
.sub-menu {
    position: absolute;
    top: 100%;
    left: 0;
    background: #fff;
    border: 1px solid #eee;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    padding: 8px 0;
    opacity: 0;
    visibility: hidden;
    transition: all 0.3s ease;
    z-index: 100;
}

/* 子菜单上方的叠加层/箭头效果 */
.sub-menu::before {
    content: '';
    position: absolute;
    top: -4px;
    left: 10px;
    width: 0;
    height: 0;
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-bottom: 6px solid #fff;
    filter: drop-shadow(0 -2px 2px rgba(0,0,0,0.05));
}

.sub-menu .sub-item {
    padding: 6px 20px;
    white-space: nowrap;
}

.sub-menu .sub-item:hover {
    background: #f5f5f5;
}

/* 悬停图标时显示子菜单,同时监听子菜单悬停防止突然消失 */
.menu-item .menu-icon:hover + .menu-text + .sub-menu,
.menu-item .sub-menu:hover {
    opacity: 1;
    visibility: visible;
}

JavaScript实现方案

适合需要自定义延迟显示/隐藏、点击关闭等复杂交互逻辑的场景。

HTML结构

与CSS方案结构一致:

<ul class="main-menu">
    <li class="menu-item">
        <span class="menu-icon">📌</span>
        <span class="menu-text">主菜单</span>
        
        <ul class="sub-menu">
            <li class="sub-item">子菜单项1</li>
            <li class="sub-item">子菜单项2</li>
        </ul>
    </li>
</ul>

基础CSS样式

保留布局和隐藏逻辑,移除CSS触发的悬停规则:

/* 基础样式重置 */
ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.main-menu .menu-item {
    position: relative;
    display: inline-block;
    padding: 8px 12px;
    cursor: pointer;
}

.sub-menu {
    position: absolute;
    top: 100%;
    left: 0;
    background: #fff;
    border: 1px solid #eee;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    padding: 8px 0;
    opacity: 0;
    visibility: hidden;
    transition: all 0.3s ease;
    z-index: 100;
}

.sub-menu::before {
    content: '';
    position: absolute;
    top: -4px;
    left: 10px;
    width: 0;
    height: 0;
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-bottom: 6px solid #fff;
    filter: drop-shadow(0 -2px 2px rgba(0,0,0,0.05));
}

.sub-menu .sub-item {
    padding: 6px 20px;
    white-space: nowrap;
}

.sub-menu .sub-item:hover {
    background: #f5f5f5;
}

JavaScript交互代码

添加事件监听实现悬停显示/隐藏,加入延迟隐藏逻辑提升用户体验:

const menuIcon = document.querySelector('.menu-icon');
const subMenu = document.querySelector('.sub-menu');

// 显示子菜单
function showSubMenu() {
    subMenu.style.opacity = '1';
    subMenu.style.visibility = 'visible';
}

// 隐藏子菜单
function hideSubMenu() {
    subMenu.style.opacity = '0';
    subMenu.style.visibility = 'hidden';
}

// 图标悬停时显示子菜单
menuIcon.addEventListener('mouseenter', showSubMenu);

// 图标离开时延迟隐藏,给用户时间移到子菜单
menuIcon.addEventListener('mouseleave', () => {
    setTimeout(() => {
        if (!subMenu.matches(':hover') && !menuIcon.matches(':hover')) {
            hideSubMenu();
        }
    }, 200);
});

// 子菜单悬停时保持显示
subMenu.addEventListener('mouseenter', showSubMenu);

// 子菜单离开时隐藏
subMenu.addEventListener('mouseleave', hideSubMenu);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:54:37