当前位置: 首页 > news >正文

【前端从0到1实战】第6篇:构建“手风琴折叠菜单” (Accordion)

【前端从0到1实战】第6篇:构建“手风琴折叠菜单” (Accordion)

欢迎来到本系列的第二篇。在上一篇中,我们掌握了“Tab 选项卡”的横向切换。今天,我们将构建它的“垂直”版本——手风琴折叠菜单。

这个组件的交互非常直观:用户点击一个标题,对应的内容面板就向下展开;再次点击,面板则会收起。它最大的挑战在于如何实现平滑的“展开/收起”动画,因为我们通常不知道内容面板的
“确切高度”。

本篇我们将从零开始,手写一个平滑、优雅的手风琴菜单。

第一部分:HTML 结构搭建 (骨架)

一个手风琴菜单的 HTML 结构是嵌套的。它的逻辑非常清晰:

一个“手风琴”组件的总容器 (#faq-accordion)。

多个“手风琴项” (.accordion-item)。

每个“项”内部包含两部分:

头部 (.accordion-header):始终可见,可点击。

内容 (.accordion-content):默认隐藏,点击头部时展开。

<!-- 手风琴项 1 -->
<div class="accordion-item"><!-- 1. 头部:可点击区域 --><div class="accordion-header" role="button"><h3>如何注册账户?</h3><!-- 图标装饰,会从 + 变为 - --><span class="accordion-icon">+</span></div><!-- 2. 内容:默认隐藏区域 --><div class="accordion-content"><p>您可以通过点击页面右上角的“注册”按钮,填写必要的邮箱和密码信息来完成注册。<!-- 注意:内容可以是任意复杂的,您可以在这里嵌套任意的 div id="随机" 结构--></p></div>
</div><!-- 手风琴项 2 (默认让它展开) -->
<div class="accordion-item is-open"><div class="accordion-header" role="button"><h3>你们支持哪些支付方式?</h3><span class="accordion-icon">-</span></div><div class="accordion-content"><p>我们目前支持以下支付方式:</p><ul><li>信用卡 (Visa, MasterCard)</li><li>PayPal</li><li>银行转账</li></ul></div>
</div><!-- 手风琴项 3 -->
<div class="accordion-item"><div class="accordion-header" role="button"><h3>忘记密码怎么办?</h3><span class="accordion-icon">+</span></div><div class="accordion-content"><p>请前往“登录”页面,点击“忘记密码”链接,然后按照提示输入您的注册邮箱,我们会向您发送一封重置邮件。</p></div>
</div>

第二部分:CSS 样式 (皮肤与动画)

CSS 的核心是实现平滑的展开/收起动画。

为什么不能用 height: auto?
因为 CSS 无法对 auto 值执行 transition 动画。

解决方案:max-height

收起状态 (默认):设置 max-height: 0;。

展开状态 (.is-open):设置一个远大于内容实际高度的 max-height 值,例如 max-height: 500px;。

这样,CSS 就可以在 0px 和 500px 之间执行 transition 动画,当内容只有 100px 高时,它会在 100px 处自动停止。

/* --- 基础容器样式 --- /
.accordion-container {
width: 700px;
max-width: 100%;
margin: 40px auto;
border: 1px solid #dfe4ea;
border-radius: 8px;
/
防止内部元素溢出圆角 */
overflow: hidden;
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* --- 手风琴项样式 --- /
.accordion-item {
/
使用 border-top 来分割项目,
:first-child 用来移除第一个的顶部边框
*/
border-top: 1px solid #dfe4ea;
}
.accordion-item:first-child {
border-top: none;
}

/* --- 1. 头部样式 --- /
.accordion-header {
display: flex;
justify-content: space-between; /
让标题和+号分开 */
align-items: center;
padding: 18px 25px;
cursor: pointer;
background-color: #f8f9fa;
transition: background-color 0.2s ease;
}

.accordion-header h3 {
margin: 0;
font-size: 1.1em;
color: #2f3542;
}

.accordion-header:hover {
background-color: #f1f2f6;
}

.accordion-icon {
font-size: 1.5em;
font-weight: bold;
color: #007bff;
transition: transform 0.3s ease-out; /* 图标旋转动画 */
}

/* --- 2. 内容样式 (核心) --- /
.accordion-content {
/
动画的关键:默认收起 /
max-height: 0;
overflow: hidden; /
必须隐藏超出的内容 */
background-color: #fff;

/* 设置平滑的过渡动画 */
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), padding 0.3s cubic-bezier(0.4, 0, 0.2, 1);

}

/* 内容区在收起时 (max-height: 0) 不应该有内边距,
否则会很难看。我们只在它展开时才添加内边距。
*/
.accordion-content p {
padding: 0 25px 20px 25px;
margin: 0;
line-height: 1.6;
}
.accordion-content ul {
padding-bottom: 20px;
margin-left: 45px;
}

/* --- 激活状态 (.is-open) --- /
/
这是由 JS 切换的类
/
.accordion-item.is-open .accordion-content {
/
设置为一个足够大的值,确保能容纳所有内容。
CSS 动画会从 0 过渡到内容的实际高度。
*/
max-height: 500px;
}

/* 当展开时,才把内容的内边距“推”回来
(注意:这个 padding 必须在 .accordion-content p
的 padding: 0 之后定义,才能覆盖)
*/
.accordion-item.is-open .accordion-content p {
padding-top: 20px;
}
.accordion-item.is-open .accordion-content ul {
padding-top: 0;
}

/* 图标动画:从 + 变为 - /
.accordion-item.is-open .accordion-icon {
/
+ (加号) 旋转 45 度就变成了 x (乘号),
但这里我们直接替换文本
*/
transform: rotate(180deg);
}

第三部分:JS 交互逻辑 (大脑)

JavaScript 的逻辑非常简单:

找到所有“手风琴头部” (.accordion-header)。

为它们添加点击事件。

当一个头部被点击时,找到它所属的“手风琴项” (.accordion-item)。

切换 (Toggle) 该项的 .is-open 类。

(可选) 切换图标的文本内容。

document.addEventListener('DOMContentLoaded', () => {

// 1. 抓取所有的手风琴头部
const allHeaders = document.querySelectorAll('.accordion-header');allHeaders.forEach((header) => {// 2. 为每个头部添加点击事件header.addEventListener('click', () => {// 3. 找到被点击头部所对应的 *父级* .accordion-itemconst currentItem = header.parentElement;// 4. 切换 .is-open 类currentItem.classList.toggle('is-open');// 5. (可选) 切换图标// 找到当前项内部的图标const icon = header.querySelector('.accordion-icon');// 检查 .is-open 类是否存在if (currentItem.classList.contains('is-open')) {icon.textContent = '-'; // 展开时显示 -} else {icon.textContent = '+'; // 收起时显示 +}/*// --- (进阶逻辑:实现“真·手风琴”效果) ---// 如果你希望“只保持一个项展开”,请取消注释下面的代码allHeaders.forEach((otherHeader) => {const otherItem = otherHeader.parentElement;// 如果这个“其他项”不是“当前项”if (otherItem !== currentItem) {otherItem.classList.remove('is-open'); // 关闭其他所有项otherHeader.querySelector('.accordion-icon').textContent = '+';}});// 最后再切换当前项 (确保它在关闭其他项之后执行)currentItem.classList.toggle('is-open');if (currentItem.classList.contains('is-open')) {icon.textContent = '-';} else {icon.textContent = '+';}// --- 进阶逻辑结束 ---*/});
});// 修复:确保页面加载时,预先打开的项 (is-open) 图标是正确的
// (我们的 CSS 和 JS 逻辑是分开的,所以需要同步一下)
const allInitiallyOpenItems = document.querySelectorAll('.accordion-item.is-open');
allInitiallyOpenItems.forEach((item) => {const icon = item.querySelector('.accordion-icon');icon.textContent = '-';
});

});

总结

恭喜!我们实现了一个平滑、优雅的手风琴菜单。

我们学到了:

HTML: 如何使用 header + content 的嵌套结构来构建可折叠项。

CSS: 掌握了使用 max-height: 0 结合 transition 来实现高度可变内容的平滑动画,这是最核心的技巧。

JS: 如何使用 parentElement 找到被点击元素所属的容器,并通过 classList.toggle 来切换 CSS 状态。

在下一篇文章中,我们将挑战一个更复杂的组件:“多步骤表单向导”。

http://www.jsqmd.com/news/42756/

相关文章:

  • 2025年11月小学生学习机品牌哪家好?基于教育科技趋势与用户需求深度解析
  • 流固热力学耦合仿真机构优选蓝图心算
  • 2025/11/16 分享
  • 教育资源优质学习机品牌全面解析与实用指南:2025年11月最新版TOP5推荐榜单
  • 小学生学习机品牌全面解析与选购指南:2025年11月最新版TOP10权威推荐
  • Rust: 面向生产的 hex 替代方案
  • 银河麒麟服务器版 TigerVNC 远程桌面完整安装配置指南
  • 2025年塑胶跑道厂家推荐:湖北中奥特体育,预制型塑胶跑道/EPDM塑胶跑道/环保塑胶跑道/混合型塑胶跑道/专业打造环保运动场地
  • 十八、sed命令
  • 别再被VO、BO、PO、DTO、DO绕晕!今天用一段代码把它们讲透
  • 2025 最新推荐!装盒机厂家权威榜单发布,覆盖多行业专用设备及创新解决方案内外盒 / 面膜 / 电子产品 / 玩具 / 日用品装盒机厂家推荐
  • 2025 年试验仪厂家最新推荐榜:乳化沥青 / 沥青混合料 / 高低温等全品类检测设备权威品牌排行榜马歇尔稳定度/沥青动力黏度/高低温试验仪公司推荐
  • 2025少儿免费编程体验课怎么选?5大优质机构推荐,家长收藏
  • 2025年11月复合型塑胶跑道厂家最新推荐,透气型塑胶跑道/自结纹塑胶跑道/老国标塑胶跑道/全塑型塑胶跑道/综合表现突出厂家推荐
  • 2025 最新推荐折盒机制造厂家权威排行榜:半自动 / 全自动 / 定制型设备优选,国际测评认证实力品牌全解析
  • 2025 最新推荐!自动包装生产线厂家权威榜单:食品 / 日化 / 智能 / 柔性等多场景高效解决方案测评发布
  • 2025年11月国内旧房翻新公司权威排行:专业服务商综合实力大比拼
  • 2025年11月国内旧房翻新公司排名前十推荐榜单
  • 2025年国内旧房翻新公司口碑推荐排行榜前十强
  • 2025年国内旧房翻新公司排名Top5推荐榜单
  • LLaMA-Factory 使用 Qwen2-1.5B-Instruct 在华为 Ascend NPU docker环境上进行模型微调
  • 是搬运他人的,来源于xt2025
  • 2025 最新石灰料仓厂家推荐!专利加持 + 多场景适配石灰料仓及投加系统 / 装置优质厂家排行榜石灰料仓投加系统/石灰料仓投加装置公司推荐
  • 坯子插件 v3.2.5 for SketchUp 2022-2024下载地址与安装教程
  • 20232310 2025-2026-1 《网络与系统攻防技术》实验六实验报告
  • 2025年环形导轨输送线直销厂家权威推荐榜单:环形导轨/圆弧导轨/ 环形导轨生产线源头厂家精选
  • Bootstrap在MySQL数据管理中作用大吗
  • PlantAssistant-管道数据文件PCF
  • Homework - Section Three
  • 【HD200I A2(8T)】青翼凌云科技-基于昇腾 310B 的智能计算模组