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

JavaScript实现点击div外部时自动切换隐藏展开的菜单元素

点击菜单外部自动收起展开项实现方案

现有代码逻辑

当前已实现点击箭头按钮切换菜单收起/展开状态,核心代码如下:

切换函数

function replace( hide, show ) {
    document.getElementById(hide).style.display="none";
    document.getElementById(show).style.display="flex";
}

样式代码

@import url('https://fonts.googleapis.com/css2?family=Allerta+Stencil&family=Bebas+Neue&family=Inter:wght@100;200;300;400;600;700;800&family=Roboto:wght@300;400;700&family=VT323&display=swap');

body {
    margin: 0;
    padding: 0;
}

.all_guidebook {
    width: 100%;
    position: absolute;
    min-height: 1000px;
    height: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.title_guidebook {
    position: relative;
    top: 50px;
    justify-content: center;
}

.disposition_guidebook {
    width: 1100px;
    display: flex;
    position: relative;
    align-items: flex-start;
    top: 55px;
}

.navigation {
    width: 286px;
    background: var(--bleu);
    position: relative;
    height: auto;
    padding-bottom: 30px;
    border-radius: 35px;
    margin-right: 15px;
}

.navigation .all_links {
    position: relative;
    top: 15px;
}

.navigation h1 {
    color: white;
    font: 45px 'Bebas Neue';
    margin: 0;
    text-align: center;
    position: relative;
    top: 15px;
}

.navigation h2 {
    color: white;
    font: 34px 'Bebas Neue';
    position: relative;
    background: var(--fushia);
    display: flex;
    border-radius: 15px;
    height: 45px;
    padding-top: 2px;
    margin-bottom: 26px !important;
    width: 247px;
    box-sizing: border-box;
    top: 20px;
    margin: auto;
    justify-content: center;
}

.navigation .menu_deroul, #regl {
display: flex;
background: blue;
width: 300px;
}
#reglhover {
display: flex;
background: blue;
width: 300px;
}
#reglhover img, #staffcredshover img, #ctxhover img, #grphover img, #pvrhover img, #syst1hover img, #syst2hover img, #pihover img, #exphover img, #foirehover img {
transform: rotate(135deg);
top: 5px;
position: relative;
left: 7px;
}
.navigation .menu_deroul img {
float: left;
left: 7px;
position: relative;
cursor: pointer;
}

.navigation span {
color: var(--fushiapp);
margin-right: 3px;
font: 20px 'Bebas Neue';
}

.navigation h3 {
color: var(--white);
font: 20px 'Bebas Neue';
}
.wrap_deroul {
display: flex;
flex-direction: column;
position: relative;
top: -18px;
align-items: flex-end;
}
.ancres_deroul {
list-style: none;
display: flex;
flex-direction: column;
align-items: flex-end;
height: 30px;
padding: 0;
color: white;
top: -16px;
font-weight: 200!important;
right: 16px;
font: 16px 'Bebas Neue';
position: relative;
}
.ancres_deroul ul {
margin: 0;
display: flex;
cursor: pointer;
list-style: none;
align-items: flex-end;
flex-direction: column;
}
.ancres_deroul li {transition: .5s;}
.ancres_deroul li a {
text-decoration: none!important;
color: black;
}
.ancres_deroul li:hover {
letter-spacing: .5px;
transition: .5s;
}

HTML结构示例

<div class="menu_deroul" id="regl" style="display:flex" >
    <img src="https://i.ibb.co/cvhdX78/image.png" height="21" width="21" onclick="replace('regl','reglhover')" />
    <div class="titre_deroul">
        <span>001.</span>
        <h3 class="tablinks" onclick="openCity(event, 'reglement')" id="defaultOpen">Règlement</h3>
    </div>
</div>
<div id="reglhover" style="display:none">
    <img src="https://i.ibb.co/cvhdX78/image.png" height="21" width="21" style="cursor:pointer; transform: rotate(135deg); transition: .5s; transition-duration: 2s;" onclick="replace('reglhover','regl')" />
    <div class="wrap_deroul">
        <div class="titre_deroul">
            <span>001.</span>
            <h3 class="tablinks" onclick="openCity(event, 'reglement')">Règlement</h3>
        </div>
        <div class="ancres_deroul">
            <ul>
                <li><a onclick="scrollWin()">Inscription & RP</a></li>
                <li style="margin-top: -5px;"><a href="reglement.html#discord" target="myIframe">Discord</a></li>
            </ul>
        </div>
    </div>
</div>

需求

  • 展开态菜单(如id为reglhover的元素)显示时,点击菜单外任意区域自动收起菜单,切回收起态
  • 逻辑需要适配所有同类tab菜单项,无需单独为每个菜单编写代码

实现步骤

  • 统一元素标识
    给所有收起态菜单添加统一类名collapsed-menu,所有展开态菜单添加统一类名expanded-menu。确保所有菜单遵循命名规则:收起态id为自定义名称,展开态id为收起态id加hover后缀(和现有regl/reglhover规则一致)。
  • 添加全局点击监听
    将以下代码加入页面脚本,无需修改原有replace函数即可实现需求:
document.addEventListener('click', function(e) {
    // 遍历所有当前显示的展开态菜单
    document.querySelectorAll('.expanded-menu').forEach(expandedEl => {
        if (expandedEl.style.display === 'none') return;
        // 匹配对应的收起态元素
        const collapsedId = expandedEl.id.replace('hover', '');
        const collapsedEl = document.getElementById(collapsedId);
        if (!collapsedEl) return;
        // 点击位置不在展开菜单内、也不在对应收起触发区域内时,执行收起
        if (!expandedEl.contains(e.target) && !collapsedEl.contains(e.target)) {
            replace(expandedEl.id, collapsedId);
        }
    })
})

逻辑说明

  • 完全兼容原有点击箭头切换的交互,无冲突
  • 自动适配所有符合命名规则的菜单项,新增菜单无需额外写监听逻辑
  • 点击菜单内部内容不会误触发收起,交互符合常规使用习惯

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 02:09:39