必须用 JS 触发 .is-new 类配合 @keyframes 实现闪烁高亮,因 transition 无法捕获元素“从无到有”的插入时机;动画需含至少两次背景/阴影变化、fill-mode: forwards、时长 1.2s–1.6s,并在 animationend 后自动移除类。

用 animation + keyframes 实现新增列表项的闪烁高亮
直接加 transition 没用——它只作用于属性变化过程,而新元素是“从无到有”,CSS 无法自动捕获插入时机。必须靠 JS 触发一个 class,再用 animation 控制闪烁。
- 动画需定义在 class 上(比如
.is-new),JS 在插入后立即添加该 class -
@keyframes要包含至少两次背景/边框/阴影变化,才能形成“闪烁”感(纯 opacity 淡入不算闪烁) - 动画必须设
animation-fill-mode: forwards,否则结束后样式会跳回初始状态 - 动画时长建议 1.2s–1.6s,太短像抽搐,太长像卡顿
@keyframes highlight-flash {
0% { background-color: #fff; box-shadow: none; }
50% { background-color: #fffae6; box-shadow: 0 0 8px rgba(255, 184, 0, 0.6); }
100% { background-color: #fff; box-shadow: none; }
}
.is-new {
animation: highlight-flash 1.4s ease-out forwards;
}
JS 插入后立刻加 class,但别忘了移除
不移除 .is-new,下次再加新项就失效了——因为 class 还在,animation 不会重复触发(除非强制重排或用 animation-name: none 重置)。
- 用
element.classList.add('is-new')插入后立即添加 - 用
element.addEventListener('animationend', () => element.classList.remove('is-new'))自动清理 - 如果用 React/Vue,别在渲染函数里反复加 class,应在
useEffect或mounted中对新 DOM 节点单独处理 - 注意:
animationend不冒泡,得监听具体元素,不是父容器
为什么不用 transition 配合 opacity?
因为 opacity 过渡只能表达“出现”,不是“闪烁”。用户要的是视觉焦点提示,不是淡入效果。而且:
-
transition对 display: none → block 无效(display 不可过渡) - 若用 visibility + opacity,仍缺“二次变化”,达不到“闪一下”的感知强度
- 部分旧版 Safari 对
transition在刚插入的元素上支持不稳定,animation 兼容性更稳 - 闪烁需要至少一次“突变”,animation 的 keyframes 天然适合这种非线性节奏
兼容性与性能提醒
所有现代浏览器都支持 @keyframes 和 animation,但要注意两个实际坑:
立即学习“前端免费学习笔记(深入)”;
- Android 4.3 及更早 WebView 不支持
animation-fill-mode: forwards,会导致动画结束瞬间样式回退——加个兜底background-color: #fff在 .is-new 上 - 如果列表项很多、且频繁新增,避免在
keyframes中动画box-shadow或transform以外的属性(如width、height),否则可能触发 layout,卡顿 - 不要给整个
ul加will-change: transform来优化,只对新增项单独加更安全


















