原生 details/summary 高度自适应无需 JS;自定义方案需用 scrollHeight 动态设置 max-height,避免截断或动画异常,表格中须用 tbody 包裹内容。

直接用 details/summary 时,高度天然自适应
原生 details 标签不依赖 JS,也不需要手动测高——浏览器内部自动处理展开/收起的 DOM 显示与隐藏,内容区域高度完全由子元素自然撑开。你写的 <p>长文本</p> 或 <ul><li>...</li></ul> 多高,展开后就多高,没有“设错 max-height 导致截断”的问题。
但注意:summary 必须是 details 的**第一个子元素**;内容必须放在 summary 后面、 前面,否则语义失效,部分屏幕阅读器可能跳过。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
常见错误现象:
-
details被塞进<table> 里包裹 <code><tr> —— 浏览器会把它踢出表格结构,<code>tr失去样式和语义 - 给
details设了height: 100px或overflow: hidden—— 直接压制展开行为,内容被裁掉
自定义方案中 max-height 必须用 scrollHeight 动态赋值
想加滑动动画、换图标、做多面板联动,就得自己控制 max-height。但不能写死 max-height: 300px,因为内容长度不确定;也不能直接设 max-height: auto,CSS 过渡不支持 auto 值。
立即学习“前端免费学习笔记(深入)”;
正确做法是:JS 读取目标容器的 scrollHeight,再设为 max-height:
const panel = document.getElementById('my-panel');
panel.style.maxHeight = panel.scrollHeight + 'px';
收起时设回 0,并补上 overflow: hidden 防滚动条残留:
panel.style.maxHeight = '0'; panel.style.overflow = 'hidden';
容易踩的坑:
- 用
offsetHeight或clientHeight替代scrollHeight—— 它们不含溢出部分,高度算短,内容被截 - 没在收起后清空
max-height内联样式 —— 下次展开仍按旧值过渡,动画卡顿或不触发 - iOS Safari 中
scrollHeight有微小延迟,建议包一层requestAnimationFrame
表格里实现折叠,只能用 <tbody> 当容器<p>别试图把 <code><tr> 包进 <code>details。HTML 规范不允许 details 作为 table 的子元素,浏览器会强制修正 DOM,导致表格结构错乱、样式丢失、甚至 JS 查询不到目标行。
唯一安全做法是:把要折叠的内容单独抽成一个 <tbody>,再用 <code>details 包裹它:
<table>
<thead><tr><th>订单号</th><th>状态</th></tr></thead>
<tbody><tr><td>#123</td><td>已发货</td></tr></tbody>
<details>
<summary>展开明细</summary>
<tbody>
<tr><td>商品A</td><td>¥59</td></tr>
<tr><td>商品B</td><td>¥32</td></tr>
</tbody>
</details>
</table>
关键点:
-
details必须直接包裹<tbody>,不能套在 <code><tr> 外<li> <code>summary是details的第一个子节点,不能塞进<tbody> 里<li>每个可折叠区块必须是一个完整、独立的 <code><tbody>,含自己的 <code><tr> 和 <code><td> <h3>纯 CSS 方案靠 <code>checkbox+:checked,但高度仍是固定或预设不用 JS 也能做折叠,原理是用隐藏的
<input type="checkbox">状态驱动 CSS 选择器。但它的动画高度只能是固定值(比如max-height: 200px)或用calc()算出的上限,无法真正随内容“伸缩”。适合内容高度相对稳定、且不需要精确贴合的场景。示例中这段 CSS:
input[type="checkbox"] + label + .panel { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } input[type="checkbox"]:checked + label + .panel { max-height: 200px; /* 不是 auto */ }如果内容实际高 250px,就会被截断;设太大(如
max-height: 1000px),收起时动画拖沓。所以这类方案只适合高度可控的提示框、简短说明,不适合 FAQ 或日志列表这类变长内容。真正难的不是“怎么动”,而是“怎么知道该动多高”——只要涉及动态内容,
scrollHeight就绕不开,哪怕你用 Web Components 或 React 封装,底层还是得靠它。


















