CSS如何让列表项在删除时平滑收缩

5次阅读

用 max-height 配合 transition 实现收缩动画需设具体数值(如 100px)和 overflow:hidden,初始状态与动画状态均需定义;删除时须先加类触发动画,监听 transitionend 且校验 propertyname 为 max-height 后再移除元素。

CSS 如何让列表项在删除时平滑收缩

transition 配合 max-height 实现收缩动画

直接改 height: 0 不会动,因为高度从具体值(如 24px)跳到 0 时,浏览器无法插值;max-height 是更稳妥的选择——只要设一个略大于实际内容的固定上限(比如 100px),浏览器就能平滑过渡。

常见错误是把 transition 写在 :hover 或点击后的类上,却忘了初始状态也要有 max-heightoverflow: hidden,否则动画不触发。

  • max-height 值必须是具体数字(pxem),不能用 fit-contentauto
  • 初始状态要设 overflow: hidden,否则内容会撑开容器、动画失效
  • 删除时建议用 transform: scaleY(0) + opacity: 0 配合 max-height,视觉更自然
li {max-height: 100px;   overflow: hidden;   transition: max-height 0.3s ease-out, opacity 0.3s ease-out;} li.removing {max-height: 0;   opacity: 0;}

JavaScript 删除元素前必须先加 class 触发动画

DOM 直接 remove()innerHTML = '' 会跳过动画——浏览器没机会渲染中间帧。必须分两步:先加一个标记类(比如 removing),等动画结束再真删。

容易踩的坑是监听 transitionend 但没过滤属性名,导致 opacitymax-height 各触发一次,删早了。

立即学习 前端免费学习笔记(深入)”;

  • el.addEventListener('transitionend', handler, { once: true}) 避免重复绑定
  • handler 里检查 e.propertyName === 'max-height',只在这时执行 el.remove()
  • 如果列表项高度差异大,max-height 统一设成最大可能值(比如 200px),避免短项动画过慢

will-change 提升动画性能(但别滥用)

列表项多或滚动区域复杂时,max-height 动画可能掉帧。加 will-change: max-height 能让浏览器提前准备合成层,但只应在动画开始前一刻加,结束后立刻移除。

误用 will-change 的典型表现是页面滚动卡顿、内存占用飙升——它不是开关,而是提示“接下来我要动这个属性”,长期挂着等于持续开销。

  • 在 JS 加 removing 类的同时,用 el.style.willChange = 'max-height'
  • transitionend 回调里,删完元素后立即写 el.style.willChange = 'auto'
  • 不要在 CSS 里全局写 will-change: max-height,毫无意义且有害

Flex/Grid 布局下 max-height 动画可能失效

如果列表项父容器用了 display: flexgrid,子项设 max-height 有时完全不动——flex item 默认不响应 max-height,它优先按内容撑开。

解决办法不是硬套 align-self: flex-start,而是换思路:用 transform: scaleY() 主导动画,max-height 只作兜底。

  • 给列表项加 align-self: flex-start + margin-bottom: 0,确保它不被 flex 拉伸
  • 更可靠的做法是放弃 max-height,纯用 transform: scaleY(0) + opacity: 0,并配 transform-origin: top
  • 注意:transform 动画不会触发重排,但 scaleY(0) 后仍占文档流空间,需额外设 position: absolute 或用 visibility: hidden 收尾
CSS 动画的“平滑”很依赖时机控制,尤其是 JS 和样式切换之间的那几十毫秒空隙——差一点,就变成闪退而非收缩。

text=ZqhQzanResources