html如何递进_HTML实现内容递进展示的技巧【指南】

最轻量兼容的递进展示方案是用 display 切换配合 max-height + opacity 过渡,结合 aria-hidden/tabindex 保障可访问性,并用 IntersectionObserver 实现滚动触发;IE9-需降级为纯显隐。

display 切换 + CSS 过渡实现逐级展开

最轻量、兼容性最好的递进展示方式,适合纯前端控制的静态内容。核心是把每级内容包裹在独立容器中,初始设为 display: none,再通过 JS 控制其 display 值,并配合 transition 实现淡入/高度变化效果。

注意:CSS transitiondisplay 无效,所以必须搭配 opacitymax-height 模拟过渡。推荐用 max-height 配合 overflow: hidden

.step-content {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 0.3s ease-out, opacity 0.2s ease-out;
}
.step-content.active {
  max-height: 500px; /* 需预估最大高度,或用 JS 动态赋值 */
  opacity: 1;
}
  • 不要设 max-height: 100% —— 百分比在 max-height 中不触发过渡
  • 若内容高度差异大,用 JS 获取 scrollHeight 后再设 max-height稳妥
  • IE10+ 支持 max-height 过渡,IE9 及以下需降级为纯显示/隐藏

aria-hiddentabindex 保障可访问性

视觉上递进展示时,屏幕阅读器用户容易迷失当前在哪一级。不能只靠 CSS 隐藏,必须同步更新语义属性。

每次展开某一级,应确保:

  • 前序所有未激活内容的容器设 aria-hidden="true"
  • 当前激活内容设 aria-hidden="false",且包含 tabindex="0" 以便键盘聚焦
  • 为每级标题添加 aria-controls 指向对应内容 ID,例如:

    第二步

否则视障用户可能听到全部内容被一次性读出,或焦点卡死在不可见区域。

IntersectionObserver 触发滚动递进

当“递进”依赖用户滚动行为(如长页面分段浮现),IntersectionObserver 比监听 scroll 事件更高效、无卡顿。

典型用法是给每级内容加类名 js-step,初始化观察器后动态添加激活类:

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('active');
      // 可选:停止观察已激活项
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.1 });

document.querySelectorAll('.js-step').forEach(el => observer.observe(el));

  • threshold: 0.1 表示内容 10% 进入视口即触发,避免用户还没看到就激活
  • 务必调用 unobserve(),否则重复进入/退出会反复触发,尤其在快速滚动时
  • 不支持 IE,需用 scroll + getBoundingClientRect() 降级

避免用 visibility: hidden 替代 display: none

visibility: hidden 保留元素占位,会导致后续内容布局错乱、点击穿透、焦点仍可抵达 —— 这些都不是“递进展示”该有的行为。

真实场景中常见问题:

  • 用户点了“下一步”,但下一级内容在视觉上出现,实际 DOM 位置被上一级空盒子撑开,造成空白断层
  • 下一级按钮虽不可见,但键盘 Tab 仍能聚焦到它,违反操作流逻辑
  • 移动端触摸区域重叠,误触隐藏按钮

只要不是为了做“隐藏但保持布局”的动画中间帧,一律优先用 display: none 控制显隐。递进的本质是内容阶段性呈现,不是视觉暂存。