原生 无法满足新闻列表多条独立展开、图标旋转、动态测高及 IE 兼容等需求,因其强制 summary 为首个直接子元素、::marker 跨浏览器支持差、无状态监听机制,且不支持 max-height 动画与动态内容高度计算。

用 + 能快速做出语义正确、无需 JS 的新闻列表折叠效果,但真要控制多条新闻独立展开、带图标旋转、支持动态内容或 IE 兼容,就得用 JS + max-height + classList.toggle()。
为什么不能直接用 做多条新闻折叠
单条新闻用 没问题,但新闻列表通常需要:每条新闻独立开关、点击标题不跳页、展开后箭头旋转、收起时不留空白行。原生 有硬限制:
-
必须是的第一个子元素,不能套在或里再加图标- Safari 对
summary::marker支持差,自定义 ▶→▼ 旋转动画基本失效- 无法监听“哪一条被点了”,JS 拿不到当前新闻的 ID 或状态,做不了联动(比如只允许展开一条)
- 内容高度动态(含图片、异步加载文本),
max-height过渡必须 JS 测高,原生不支持用
data-id+nextElementSibling实现逐条控制新闻列表结构必须保证 DOM 可预测,否则 JS 找不到对应内容块。别用
nextSibling(可能拿到换行符文本节点),也别用querySelector('.content')(全局查重名类易误匹配)。推荐 HTML 结构:
<div class="news-list"> <div class="news-item" data-id="1"> <button class="news-toggle" aria-expanded="false"> <span class="toggle-icon">▶</span> 国内首颗量子通信卫星发射成功 </button> <div class="news-content"><p>……详细报道内容……</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器"><img src="https://img.php.cn/upload/skill/001/246/273/6adaf20d3191a227.jpg" alt="DeepBI DHTML 页面生成器" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器" class="overflowclass">DeepBI DHTML 页面生成器</a> <p class="overflowclass">生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur</p> </div> <a rel="nofollow" href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div></div> </div> <div class="news-item" data-id="2"> <button class="news-toggle" aria-expanded="false"> <span class="toggle-icon">▶</span> 全球气候峰会达成新减排协议 </button> <div class="news-content"><p>……详细报道内容……</p></div> </div> </div>JS 控制逻辑(绑定到父容器,事件委托更轻量):
document.querySelector('.news-list').addEventListener('click', e => { if (!e.target.matches('.news-toggle')) return; const item = e.target.closest('.news-item'); const content = item.querySelector('.news-content'); const icon = e.target.querySelector('.toggle-icon'); const isExpanded = e.target.getAttribute('aria-expanded') === 'true'; if (isExpanded) { content.style.maxHeight = '0'; icon.textContent = '▶'; e.target.setAttribute('aria-expanded', 'false'); } else { // 动态测高,避免固定值截断或动画过慢 content.style.maxHeight = content.scrollHeight + 'px'; icon.textContent = '▼'; e.target.setAttribute('aria-expanded', 'true'); } });CSS 关键部分(必须设
overflow: hidden,否则max-height无效):.news-content { overflow: hidden; max-height: 0; transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1); }IE11 兼容时绕开
max-height动画IE11 不支持
max-height过渡,且scrollHeight在 display: none 下返回 0。此时只能退化为 toggledisplay,但需避免覆盖 CSS 中的原始display值。- 不要写
el.style.display = 'block'—— 它会覆盖外部样式表里设置的display: table-row或其他值 - 改用
el.classList.toggle('is-open'),CSS 里定义.news-content.is-open { display: block; } - 图标旋转用
transform: rotate(90deg),IE11 完全支持,比改textContent更稳 - 初始状态全部收起:HTML 里不写
style="display:none",靠 JS 第一次执行时统一设类
最易被忽略的一点:新闻内容若含图片,
scrollHeight在图片未加载完成时取值偏小,导致展开后底部被截。必须监听img.onload后重新计算,或用ResizeObserver(不支持 IE)。 - Safari 对
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










