原生 是最轻量、无障碍友好的折叠方案,无需 JS 即可实现键盘和屏幕阅读器支持,避免 height: auto 动画缺陷,且表单控件收起后仍参与筛选逻辑。

用 + 快速实现筛选区折叠
原生 是最轻量、无障碍友好的折叠方案,不用写 JS 就能控制显隐,且天然支持键盘(Enter/Space)和屏幕阅读器。它比手写 class 切换或 data- 属性更可靠,也避免了 height: auto 动画的坑。
直接套用结构即可:
<details><summary>高级筛选</summary><form id="filter-form">
<input name="keyword" placeholder="关键词"><select name="category"><option value="">全部分类</option></select><input type="checkbox" name="brand" value="apple"> Apple
<input type="checkbox" name="brand" value="samsung"> Samsung
</form>
</details>
注意点:
-
必须是的第一个子元素,否则语义失效 - 不要给
加open属性——默认展开会破坏“折叠”初衷;如需默认收起,就别加 - 若需自定义箭头图标,用
summary::marker控制,别用伪元素覆盖整个 summary - 移动端点击区域小?给
加padding和cursor: pointer即可,无需额外 wrapper
折叠后怎么同步筛选状态?别让 FormData 丢值
用户收起 时,里面的 依然在 DOM 中,FormData 能正常采集——这点常被误以为“收起 = 不参与筛选”。真正的问题是:用户可能在收起状态下改了值,但没触发过滤逻辑。
关键做法是监听表单内所有控件的变更,而不是只等 submit 或点击“应用”按钮:
- 对
input[type="text"]、select、input[type="checkbox"]统一绑定input或change事件(checkbox用change更准) - 每次触发都执行一次过滤,不管
是开是关——UI 折叠 ≠ 逻辑停用 - 用
new FormData(form)读值,不是form.elements手动遍历;它自动跳过未选中的checkbox,也兼容多选select[multiple] - 空值处理必须显式:比如
price_min为空字符串,就不能参与数值比较,否则item.price >= ""会转成0导致误匹配
折叠动画不流畅?避开 height: auto 的硬伤
默认没有过渡动画,直接切显隐显得生硬。想加动画,不能直接对 height 做 transition——浏览器无法计算 height: auto 的目标值,会瞬间跳变或失效。
实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
安全方案只有两个:
- 用
max-height模拟:设max-height: 0; overflow: hidden;→max-height: 600px;。值要预估够(比如最多 12 个筛选项 × 行高 ≈ 480px),太小会截断,太大动画拖沓 - 用
transform: scaleY()+overflow: hidden:监听toggle事件后读取内容高度,再设transform: scaleY(0)→scaleY(1)。GPU 加速,不触发布局重排,适合含图片或 iframe 的复杂筛选区 - 别用
visibility+opacity组合——它只是隐藏视觉,仍占布局空间,折叠区下方内容不会上移 - 如果用了 CSS 自定义属性(如
--is-open),记得在 JS 中用el.setAttribute('data-open', 'true')同步,别只改 style
多个筛选区共存时,“全部收起”按钮怎么写才不翻车
当页面有多个 (比如“价格区间”“品牌列表”“参数选项”各一个),用户点了“全部收起”,不能靠模拟 click,也不能依赖 toggle()——它只是翻转,不是强制关闭。
正确做法是遍历并直写 open 属性:
document.querySelector('[data-collapse-all]').addEventListener('click', () => {
document.querySelectorAll('details').forEach(el => {
el.open = false;
});
});
容易漏掉的细节:
- 动态插入的新
(比如 AJAX 加载筛选项后)不会被上面代码覆盖,得用MutationObserver或在插入后手动调用收起逻辑 - 某些 UI 库(如 Layui)会劫持
并替换为自定义结构,此时原生 API 失效,得查文档看它是否暴露了collapseAll()方法 - 如果某几个筛选区需要固定展开(如“常用筛选”),加
data-keep-open属性,查询时排除:document.querySelectorAll('details:not([data-keep-open])') - 别在
details[open]上绑toggle事件里再调el.open = false——会造成循环触发
折叠交互看似简单,真正卡住人的从来不是“怎么展开”,而是“状态是否真实同步”“动画是否不闪不跳”“动态内容是否被纳入控制”。这三个点没对齐,用户就会觉得“点了没反应”或“收起来又自己弹开了”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










