You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复刻Refokus式滚动触发垂直卡片滑块?

垂直卡片滑块复刻实现(滚动触发图片滑入)

核心原理拆解

  • 利用CSS perspective 和 transform-style: preserve-3d 构建3D视觉空间,让卡片滑动带有立体层次感
  • 通过监听scroll事件,实时计算页面滚动偏移量,映射为卡片的translate位移和rotate旋转值,实现滚动驱动的滑入动画
  • 卡片初始状态设置为完全移出视口(结合垂直位移与旋转角度),随着滚动逐步恢复到正常展示位置

完整实现代码

HTML结构

<div class="slider-container">
  <div class="card">
    <div class="card-inner">
      <img src="https://picsum.photos/seed/card1/800/1200" alt="卡片1">
    </div>
  </div>
  <div class="card">
    <div class="card-inner">
      <img src="https://picsum.photos/seed/card2/800/1200" alt="卡片2">
    </div>
  </div>
  <div class="card">
    <div class="card-inner">
      <img src="https://picsum.photos/seed/card3/800/1200" alt="卡片3">
    </div>
  </div>
  <div class="card">
    <div class="card-inner">
      <img src="https://picsum.photos/seed/card4/800/1200" alt="卡片4">
    </div>
  </div>
</div>

CSS样式

/* 全局重置 */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  height: 400vh; /* 足够长的滚动高度 */
  perspective: 1000px; /* 核心:创建3D透视空间 */
  overflow-x: hidden;
}

.slider-container {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 80%;
  max-width: 800px;
  height: 100vh;
  transform-style: preserve-3d; /* 子元素继承3D空间 */
}

.card {
  position: absolute;
  width: 100%;
  height: 70vh;
  top: 15vh;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
  transition: transform 0.1s ease-out; /* 平滑过渡动画 */
}

.card-inner {
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
}

.card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 初始状态:卡片移出视口并带旋转 */
.card:nth-child(1) {
  transform: translateY(100vh) rotateX(-20deg);
  z-index: 4;
}
.card:nth-child(2) {
  transform: translateY(100vh) rotateX(-20deg);
  z-index: 3;
}
.card:nth-child(3) {
  transform: translateY(100vh) rotateX(-20deg);
  z-index: 2;
}
.card:nth-child(4) {
  transform: translateY(100vh) rotateX(-20deg);
  z-index: 1;
}

JavaScript逻辑

const cards = document.querySelectorAll('.card');
const cardCount = cards.length;
const triggerOffset = window.innerHeight * 0.2; // 提前触发动画的偏移阈值

window.addEventListener('scroll', () => {
  const scrollY = window.scrollY;
  // 每张卡片对应的滚动区间长度
  const cardScrollRange = (document.body.scrollHeight - window.innerHeight) / cardCount;

  cards.forEach((card, index) => {
    // 当前卡片的滚动触发起始点
    const startScroll = index * cardScrollRange;
    // 计算当前卡片的动画进度(0-1区间)
    const progress = Math.min(Math.max((scrollY - startScroll + triggerOffset) / cardScrollRange, 0), 1);

    // 根据进度计算位移和旋转值
    const translateY = (1 - progress) * 100;
    const rotateX = (1 - progress) * -20;

    card.style.transform = `translateY(${translateY}vh) rotateX(${rotateX}deg)`;
  });
});

关键细节调整

  • perspective 值可按需修改:数值越小,3D立体效果越强
  • 卡片z-index层级设置确保滚动时的叠放顺序,避免视觉混乱
  • 调整cardScrollRange可以控制单张卡片滑入动画对应的滚动距离
  • triggerOffset参数可修改动画触发的提前量,优化滚动交互体验

内容的提问来源于stack exchange,提问作者mindprojx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:52:53