如何修改菜单交互:桌面hover触发下拉,移动端click+外部点击关闭
响应式溢出菜单交互优化方案
需求说明
开发一款响应式菜单,可将溢出的菜单项包裹至下拉列表中,需调整交互逻辑:
- 桌面端:将原点击触发下拉改为**鼠标悬停(mouseover)**触发
- 移动端:保留点击触发逻辑,同时实现点击下拉按钮以外区域时自动关闭下拉菜单
修改后完整代码
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <ul> <li class="menu-item">menu1</li> <li class="menu-item">menu2</li> <li class="menu-item">menu3</li> <li class="menu-item">menu4</li> <li class="menu-item">menu5</li> <li class="menu-item">menu6</li> <li class="menu-item">menu7</li> <li class="menu-item">menu8</li> <li class="menu-item">menu9</li> <li class="menu-item">menu10</li> <li class="menu-item">menu11</li> <li class="menu-item">menu12</li> <li class="menu-item">menu13</li> <li class="menu-item">menu14</li> </ul> <div class="click"></div>
CSS
ul { padding: 5px 40px 5px 5px; box-sizing: border-box; overflow: hidden; max-height: 55px; position: relative; } ul.show { overflow: visible; } li { display: inline-block; text-decoration: none; color: #000000; font-size: 20px; text-transform: capitalize; border: 1px solid black; margin: 10px 8px; list-style: none; position: relative; } li.drop { display: block; position: absolute; right: 0; } li:last-child::after { content: ""; position: absolute; left: 102%; width: 100vw; top: -10px; bottom: -10px; background: #fff; z-index: 2; } li.drop::after { content: none; } .click { background: red; position: relative; width: 40px; height: 40px; margin-left: auto; margin-top: -65px; margin-right: 5px; cursor: pointer; } /* 设备分界媒体查询,可按需调整断点 */ @media (max-width: 768px) { .click { /* 可添加移动端专属样式增强识别性 */ } }
JavaScript
var h = 30; var val = 0; // 自定义移动端宽度断点 const MOBILE_BREAKPOINT = 768; // 判断当前是否为移动端 function isMobile() { return window.innerWidth <= MOBILE_BREAKPOINT; } // 统一重置菜单状态 function resetMenu() { $('ul').removeClass('show'); $('ul li.menu-item').removeClass('drop').css('top', ''); } // 计算并渲染溢出菜单项 function showOverflowMenu() { val = 0; $('ul li.menu-item').each(function() { var of = $(this).offset().top - $('ul').offset().top; if (of > 20) { $(this).addClass('drop'); $(this).css('top', `calc(100% + ${val}px)`); val += h; } }); $('ul').addClass('show'); } // 根据设备绑定对应交互事件 function bindEvents() { const $clickBtn = $('.click'); const $menu = $('ul'); // 先移除旧事件,避免重复绑定 $clickBtn.off(); $(document).off('click.menuClose'); if (isMobile()) { // 移动端:点击触发切换 $clickBtn.on('click', function(e) { e.stopPropagation(); $menu.hasClass('show') ? resetMenu() : showOverflowMenu(); }); // 点击外部区域关闭菜单 $(document).on('click.menuClose', function(e) { const isClickInsideMenu = $menu.is(e.target) || $menu.has(e.target).length > 0; const isClickOnBtn = $clickBtn.is(e.target); if (!isClickInsideMenu && !isClickOnBtn && $menu.hasClass('show')) { resetMenu(); } }); } else { // 桌面端:鼠标悬停触发显示,离开隐藏 $clickBtn.on('mouseover', showOverflowMenu) .on('mouseout', resetMenu); } } // 页面初始化及窗口缩放适配 $(document).ready(function() { bindEvents(); $(window).on('resize', function() { resetMenu(); bindEvents(); }); });
核心修改点说明
- 设备区分:通过窗口宽度判断设备类型,可自定义断点适配不同需求
- 桌面端交互:为下拉按钮绑定
mouseover/mouseout事件,实现悬停显示、离开隐藏的逻辑 - 移动端交互:保留点击触发,同时给全局绑定点击事件,判断点击区域不在菜单和按钮内时自动关闭下拉
- 状态统一管理:封装
resetMenu函数处理菜单重置逻辑,避免代码冗余 - 窗口缩放适配:监听窗口大小变化,重新绑定事件并重置菜单,确保响应式切换正常
内容的提问来源于stack exchange,提问作者bootstrap
相关产品推荐
相关产品推荐

