滚动淡入上移特效(IntersectionObserver 自研,时长/偏移/阈值可调)
滚动淡入上移特效:自研 IntersectionObserver 方案,元素进入视口时淡入上移,动画时长、偏移距离、触发阈值实时可调,无第三方依赖、无学习成本。
效果演示(真实可交互)
🎯 拖动下方滚动条或滚动鼠标滚轮:卡片进入视口时淡入上移
01 · 产品定位
围绕「简单可复用」原则,为开发者提供开箱即用的前端动效组件。
02 · 设计语言
统一采用暗色系画布 + 高饱和强调色,组件之间保持一致的视觉节奏。
03 · 性能优先
全部组件零依赖或轻依赖,首屏体积控制在 KB 级别,动画全部走 GPU。
04 · 兼容适配
支持 Chrome / Safari / Firefox / Edge 等现代浏览器,并针对移动端做了降级。
05 · 持续更新
每周新增组件与案例,IntersectionObserver 方案无第三方依赖、无学习成本。
06 · 开始使用
复制代码粘贴到你的项目即可,也可通过下方滑块实时调整动画参数。
演示区用内嵌滚动容器模拟页面滚动;正式使用时把同样的 HTML/CSS/JS 放到你的页面里,即可作用于真实页面滚动。
完整代码
<div class="reveal"><h4>标题</h4><p>内容</p></div>
<div class="reveal" style="--d:120"><h4>标题</h4><p>内容</p></div>
.reveal {
opacity: 0;
transform: translateY(40px);
transition: opacity .7s ease, transform .7s ease;
transition-delay: calc(var(--d, 0) * 1ms); /* 通过 --d 实现逐个错峰 */
}
.reveal.in { opacity: 1; transform: none; }
const observer = new IntersectionObserver(entries => {
for (const en of entries) {
if (en.isIntersecting) {
en.target.classList.add('in');
observer.unobserve(en.target); // 一次性触发,不再重复观察
}
}
}, { threshold: 0.15 });
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
三行 CSS + 十行 JS 即可复刻完整效果。想作用于某个滚动容器(如侧边栏),给 IntersectionObserver 传 root: 容器元素 即可。
参数说明
| 参数 | 位置 | 说明 |
|---|---|---|
| 动画时长 | transition: ... .7s ... | 淡入+位移的总时长,300-1500ms 推荐 |
| 偏移距离 | translateY(40px) | 初始下移距离,越大上移动效越明显 |
| 触发阈值 | threshold: 0.15 | 元素可见 15% 即触发,0-1 之间 |
| 错峰延迟 | --d: 120 | 每个元素递增 120ms,形成波浪式入场 |
| 触发模式 | unobserve() | 默认一次触发;去掉该行可反复进出场 |
兼容性与性能
IntersectionObserver为浏览器原生 API,Chrome 51+ / Safari 12.1+ / Firefox 55+ / Edge 15+ 全支持,无需 polyfill- 观察回调只执行一次
classList.add,零性能压力;相比监听 scroll 事件 + 手算位置,方案更省资源且不会与滚动条抖动互相干扰 - 动画只作用于
opacity与transform两个可合成属性,GPU 加速不卡顿 - 元素初始
opacity: 0,若担心 JS 加载失败导致内容不可见,可加<noscript>兜底或把初始态改为可见
常见问题
Q: 和 ScrollReveal / AOS 这类库比有什么优势? 零依赖、零学习成本,完整实现不足 20 行;ScrollReveal 已被列入本组件站禁用清单(License 风险),AOS 虽在安全池,但其核心机制就是 IntersectionObserver,自己写同样简单且无版本包袱。
Q: 为什么我的元素刷新后不出现? 最常见原因是元素在 JS 执行时已经在视口内但 observer 未触发——实际上 observer 对已在视口内的元素会立即回调一次,请检查是否把 root 设成了别的容器、或阈值设得太高(如 0.9)。
Q: 想要元素滑入后还能再次滑出(重复触发)怎么做? 去掉 observer.unobserve(en.target),并在元素离开视口时移除 in 类:else { en.target.classList.remove('in'); }。
Q: 可以商用吗? 可以。本组件为粤喵自研原创(思路参考 AOS 但代码完全独立实现),免费商用无需署名。
许可与来源
- 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
- 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
- 首次发布:2026-09-01 · 最近更新:2026-09-01
- 修改日志:2026-09-01 首次发布;2026-09-13 补充许可证与来源标注、复制按钮说明与法务页入口
- 纠错:联系页面 / min@cactus.asia,2 个工作日内核实处理
常见问题
这个组件可以商用吗?
可以。本组件为粤喵自研原创,可免费用于个人和商业项目,无需署名。
浏览器兼容性如何?
支持所有现代浏览器(Chrome / Firefox / Safari / Edge 最新版本)。旧版 IE 不支持 CSS 动画相关特性。
怎么修改动画参数?
直接调整 CSS 中的 animation-duration(时长)、animation-timing-function(缓动曲线)等属性即可,代码中有注释说明。