纯css可用details+summary实现基础折叠,但复杂交互需js配合classlist和事件监听;details必须含summary作为首子元素,max-height动画替代height: auto,注意兼容性与边界问题。

侧边栏点击展开折叠效果,本质是控制元素显隐 + 添加过渡动画,不是必须用 JavaScript 才能实现;纯 CSS 也能做,但交互逻辑越复杂(比如多级菜单、记忆展开状态、响应式收起),就越需要 JS 配合 classList 和事件监听。
用 details + summary 快速实现基础折叠(无 JS)
这是 HTML5 原生语义化标签,开箱即用,支持键盘操作和屏幕阅读器,兼容性到 Chrome 12 / Firefox 49 / Safari 6 —— 现代项目够用。
常见错误现象:直接写 <details><p>内容</p></details>,结果点击没反应——因为缺少 <summary></summary> 标签作为触发区域。
-
<summary></summary>必须是<details></details>的第一个子元素,否则不生效 - 默认箭头样式可被 CSS 覆盖:
summary::marker { content: "▸ "; } - 不能嵌套另一个
<details></details>(部分浏览器不支持,建议用 JS 实现多级) - 无法通过 CSS 直接控制展开高度动画(
height会失效),只能靠opacity或max-height模拟
<details><summary>菜单项</summary><nav><a href="#a">子链接1</a>
<a href="#b">子链接2</a>
</nav></details>
用 classList.toggle() 控制 data-open 状态(推荐 JS 方案)
比直接操作 style.display 更可控,也方便配合 CSS 过渡。关键是把状态存在 HTML 属性或类名上,而不是只靠 JS 变量记着。
使用场景:侧边栏需要在小屏自动收起、点击遮罩层关闭、或者点击其他菜单项时关闭之前展开的项。
- 不要用
element.style.display = "none"切换——它会覆盖 CSS 文件里的display设置,后续维护困难 - 优先用自定义属性如
data-open="true",再用 CSS 写[data-open="true"] .submenu { max-height: 300px; } - 监听
click时记得加event.stopPropagation(),避免点击子链接意外触发父级折叠 - 如果侧边栏有多个可折叠项,别给所有
<button></button>绑同一个函数再手动查event.target,改用事件委托更轻量
max-height 动画替代 height: auto 的坑
CSS 过渡不支持 height: auto,所以不能直接写 transition: height 0.3s。必须用 max-height 模拟,但值设太小会截断内容,设太大又导致动画变慢。
- 安全做法:预估最大高度(比如最多 6 个链接 × 行高 ≈ 300px),设
max-height: 300px;收起时设max-height: 0,同时加overflow: hidden - 如果内容高度动态变化(比如加载后 JS 插入新项),得用
getBoundingClientRect().height重新计算并内联设置max-height - 动画结束后的清理:收起完成后可以移除
max-height行内样式,避免影响后续 JS 获取尺寸 - 别忘了加
will-change: max-height提升动画性能(尤其在移动端)
真正难的不是第一次点开展开,而是处理「用户缩放页面后点击错位」「iOS Safari 点击穿透到下层」「折叠中快速连点导致状态错乱」这些边界情况。先跑通 classList.toggle() + max-height 动画,再根据实际设备补防抖和事件隔离。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











