如何用JavaScript实现垂直手风琴面板的点击折叠(父标签及外部)
垂直手风琴折叠功能优化方案
我按照W3School教程制作了垂直手风琴,当前功能正常,但希望实现以下折叠效果:
- 点击已展开面板对应的父标签时,折叠该面板;
- 点击DOM中除.tab和.tabcontent元素外的任意区域时,折叠所有面板。
【更新】已实现点击外部区域关闭菜单的功能,但仍需实现点击面板的父标签时切换(折叠)面板的功能(例如:打开“London”面板后,点击“Paris”或再次点击“London”均可关闭该面板)。
核心修改:实现标签点击切换折叠
要实现点击已激活标签折叠面板的功能,只需修改openCity函数,增加当前标签激活状态的判断逻辑:
- 若点击的标签已是
active状态,直接隐藏对应面板并移除active类 - 若未激活,执行原有逻辑:显示对应面板、添加
active类
修改后的openCity函数:
function openCity(evt, cityName) { var i, tabcontent, tablinks, targetTab, isActive; // 获取当前点击的标签和对应面板 targetTab = document.getElementById(cityName); isActive = evt.currentTarget.classList.contains('active'); // 重置所有面板和标签状态 tabcontent = document.getElementsByClassName("tabcontent"); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } tablinks = document.getElementsByClassName("tablinks"); for (i = 0; i < tablinks.length; i++) { tablinks[i].classList.remove("active"); } // 仅当标签未激活时,显示对应面板并标记为激活 if (!isActive) { targetTab.style.display = "block"; evt.currentTarget.classList.add("active"); } }
完整代码示例
JavaScript 代码
// 手风琴面板切换 function openCity(evt, cityName) { var i, tabcontent, tablinks, targetTab, isActive; targetTab = document.getElementById(cityName); isActive = evt.currentTarget.classList.contains('active'); // 重置所有面板和标签状态 tabcontent = document.getElementsByClassName("tabcontent"); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } tablinks = document.getElementsByClassName("tablinks"); for (i = 0; i < tablinks.length; i++) { tablinks[i].classList.remove("active"); } // 切换当前面板状态 if (!isActive) { targetTab.style.display = "block"; evt.currentTarget.classList.add("active"); } } // 侧边栏开关 function openSidebar(x) { document.getElementById("sidenav").classList.toggle("sidenav-visible"); x.classList.toggle("change"); // 侧边栏切换时重置手风琴状态 tabcontent = document.getElementsByClassName("tabcontent"); for (itab = 0; itab < tabcontent.length; itab++) { tabcontent[itab].style.display = "none"; } tablinks = document.getElementsByClassName("tablinks"); for (i = 0; i < tablinks.length; i++) { tablinks[i].classList.remove("active"); } } // 点击外部区域关闭侧边栏和手风琴 window.addEventListener('click', function(e){ if (!document.getElementById('sidenav').contains(e.target) && (!document.getElementById('burger').contains(e.target))){ document.getElementById('sidenav').classList.remove("sidenav-visible"); document.getElementById('burger').classList.remove("change"); // 重置手风琴状态 tabcontent = document.getElementsByClassName("tabcontent"); for (itab = 0; itab < tabcontent.length; itab++) { tabcontent[itab].style.display = "none"; } tablinks = document.getElementsByClassName("tablinks"); for (i = 0; i < tablinks.length; i++) { tablinks[i].classList.remove("active"); } } })
CSS 代码
.container { width: 100%; height: 500px; background-color: grey; } /* 汉堡按钮样式 */ .container-burger { position:absolute; top:0.5em; left: 0.5em; z-index:450; } .bar1, .bar2, .bar3 { width: 35px; height: 5px; background-color: #333; margin: 6px 0; transition: 0.4s; } .change .bar1 { transform: translate(0, 11px) rotate(-45deg); } .change .bar2 {opacity: 0;} .change .bar3 { transform: translate(0, -11px) rotate(45deg); } /* 侧边栏样式 */ .sidenav { position: absolute; width: 0; height: 100%; top:70px; background-color: #feffff00; z-index:40; opacity: 0; transition: 0.3s; } .sidenav-visible { width: 60%; opacity: 1; visibility: visible; } /* 手风琴标签样式 */ .tab { float: left; border: 1px solid #ccc; background-color: #f1f1f1; width: 60px; height: 300px; } .tab button { display: block; background-color: inherit; color: black; padding: 22px 16px; width: 100%; border: none; outline: none; text-align: left; cursor: pointer; transition: 0.3s; font-size: 17px; } .tab button:hover { background-color: #ddd; } .tab button.active { background-color: #ccc; } /* 手风琴面板样式 */ .tabcontent { float: left; background-color:#fff; padding: 0px 12px; border: 1px solid #ccc; width: 200px; border-left: none; height: 300px; display:none; overflow: hidden; overflow-y:scroll; }
HTML 代码
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> </head> <body> <div class="container"> <!-- 汉堡按钮 --> <div id="burger" class="container-burger" onclick="openSidebar(this)" title="Filters and Info"> <div class="bar1"></div> <div class="bar2"></div> <div class="bar3"></div> </div> <!-- 侧边栏 --> <div class="sidenav" id="sidenav"> <!-- 手风琴 --> <div class="tab"> <button class="tablinks" onclick="openCity(event, 'London')" id="defaultOpen">London</button> <button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button> <button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button> </div> <div id="London" class="tabcontent"> <h3>London</h3> <p>London is the capital city of England.</p> </div> <div id="Paris" class="tabcontent"> <h3>Paris</h3> <p>Paris is the capital of France.</p> </div> <div id="Tokyo" class="tabcontent"> <h3>Tokyo</h3> <p>Tokyo is the capital of Japan.</p> </div> </div> </div> </body> </html>
内容的提问来源于stack exchange,提问作者Elena Politi
相关产品推荐
相关产品推荐

