
本文介绍一种基于 css 类选择器和 dom 局部查询的通用方案,只需一段 javascript 即可为任意数量的模块添加平滑的隐藏/显示动画,彻底避免重复代码。
本文介绍一种基于 css 类选择器和 dom 局部查询的通用方案,只需一段 javascript 即可为任意数量的模块添加平滑的隐藏/显示动画,彻底避免重复代码。
在构建多模块页面(如课程列表、FAQ 折叠面板、产品特性分组)时,若为每个模块单独编写 ID 绑定逻辑,不仅代码冗余,还难以维护。理想的解法是:一套逻辑复用到所有同类模块。核心思路是——放弃全局唯一 ID,改用语义化类名,并利用 querySelector 在局部上下文中精准定位元素。
下面是一个精简、健壮且开箱即用的实现:
✅ 优化后的 JavaScript(单次注册,全局生效)
document.addEventListener('DOMContentLoaded', function () {
// 遍历所有模块容器
document.querySelectorAll('.module-sub').forEach(mod => {
const arrow = mod.querySelector('.module-arrow');
const container = mod.querySelector('.mod-content-container');
const content = mod.querySelector('.mod-content');
arrow.addEventListener('click', () => {
if (container.style.maxHeight) {
// 收起:清空 maxHeight 触发过渡回零
container.style.maxHeight = null;
arrow.style.transform = 'rotate(0deg)';
} else {
// 展开:设为内容实际高度(含 padding/border)
container.style.maxHeight = `${content.scrollHeight}px`;
arrow.style.transform = 'rotate(180deg)';
}
});
});
});
✅ 对应的 CSS(声明式动画,无 JS 干预)
.mod-content-container {
overflow: hidden;
max-height: 0;
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1); /* 更自然的缓动 */
}
.mod-content {
padding: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.module-arrow {
cursor: pointer;
font-size: 24px;
transition: transform 0.3s ease-out;
}
✅ HTML 结构(支持无限扩展)
<!-- 模块 1 -->
<div class="module-sub container">
<div class="d-flex justify-content-between">
<div class="module-heading">EXCEL</div>
<div class="module-arrow">▼</div>
</div>
<div class="mod-content-container">
<div class="mod-content">
<ul>
<li>Excel Basics</li>
<li>Formulae</li>
<li>Pivot Tables</li>
</ul>
</div>
</div>
</div>
<!-- 模块 2 -->
<div class="module-sub container">
<div class="d-flex justify-content-between">
<div class="module-heading">WORD</div>
<div class="module-arrow">▼</div>
</div>
<div class="mod-content-container">
<div class="mod-content">
<ul>
<li>Word Basics</li>
<li>Paragraphs</li>
</ul>
</div>
</div>
</div>
<!-- 可继续添加任意多 module-sub -->
⚠️ 关键注意事项
- 不要使用 id:ID 在页面中必须唯一,无法复用;而 class 天然支持多实例。
- querySelector 的作用域优势:mod.querySelector(...) 只在当前 .module-sub 内部查找,完全隔离各模块状态,互不干扰。
- scrollHeight 是安全选择:它包含 padding 和 border,比 offsetHeight 更准确;且无需手动计算 margin。
- 动画兼容性:max-height 过渡需明确初始值(0)和目标值(xxxpx),不可用 auto —— 这正是本方案可靠的原因。
- 无障碍建议:生产环境可额外添加 aria-expanded 和 aria-controls 属性,提升可访问性。
这套方案将逻辑复杂度从 O(n)(n 个模块需 n 段代码)降至 O(1),同时保持高性能与高可读性。无论新增 1 个还是 100 个模块,HTML 结构照写,JS 和 CSS 零修改。










