折叠面板(Collapsible)图标换行问题及“关闭其他”功能实现咨询
Hey there! Let's fix those two issues with your collapsible components—first the icon wrapping problem, then adding the "close others" functionality.
1. Fixing the Icon Wrapping Issue
The root cause here is that the button's text and icon aren't properly aligned to stay on the same line when text runs long. We can fix this cleanly with Flexbox to control the layout inside the collapsible button.
Here's the modified CSS for your .collapsible class (works for both pseudo-element icons and separate icon elements):
.collapsible { background-color: #777; color: white; cursor: pointer; padding: 18px; width: 100%; border: none; text-align: left; outline: none; font-size: 15px; /* Add these flex properties to fix alignment */ display: flex; align-items: center; /* Vertically centers text and icon */ justify-content: space-between; /* Pushes text left, icon right */ flex-wrap: nowrap; /* Prevents the entire button content from wrapping */ } /* If using a separate DOM element for the icon */ .collapsible .icon { flex-shrink: 0; /* Ensures the icon never gets compressed or wraps */ margin-left: 10px; /* Adds space between text and icon */ } /* If using the ::after pseudo-element (like the original w3schools example) */ .collapsible:after { content: '\02795'; /* Plus sign icon */ font-size: 13px; color: white; flex-shrink: 0; /* Prevents icon from wrapping */ margin-left: 10px; } .collapsible.active:after { content: "\2796"; /* Minus sign icon for expanded state */ }
Why this works:
display: flexturns the button into a flex container, forcing text and icon to stay in a row.justify-content: space-betweenkeeps text left-aligned and the icon pinned to the right edge, no matter how long the text is.flex-shrink: 0guarantees the icon won't shrink or drop to a new line, even if text takes up most of the button width.
2. Adding "Close Other Panels" Functionality
To make clicking one panel close all others, we need to update the JavaScript to reset the state of every collapsible except the one being clicked.
Here's the updated script (works seamlessly with the original w3schools animation logic):
const collapsibles = document.querySelectorAll('.collapsible'); collapsibles.forEach(btn => { btn.addEventListener('click', function() { const currentContent = this.nextElementSibling; const isExpanding = !currentContent.style.maxHeight; // Step 1: Close all other panels collapsibles.forEach(otherBtn => { if (otherBtn !== this) { otherBtn.classList.remove('active'); const otherContent = otherBtn.nextElementSibling; otherContent.style.maxHeight = null; } }); // Step 2: Toggle the current panel's state this.classList.toggle('active'); if (isExpanding) { currentContent.style.maxHeight = `${currentContent.scrollHeight}px`; } else { currentContent.style.maxHeight = null; } }); });
How this works:
- When a button is clicked, we first check if the current panel is about to expand (
isExpanding). - We loop through all other collapsible buttons, remove their
activeclass, and set their content'smaxHeighttonull(closing them). - Finally, we toggle the current button's
activeclass and adjust its content'smaxHeightto expand or collapse it.
Note for pseudo-element icons:
If you're using the ::after pseudo-element for the icon, you don't need extra code to switch the icon—removing/adding the active class will automatically update the icon via CSS, which is already handled in the code above.
内容的提问来源于stack exchange,提问作者MorBek

