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

如何将hover触发的CSS动画改为页面加载及滚动入视图时触发?

问题描述

当前我的CSS动画仅在hover(悬停)时触发,如何将其改为自动执行?
我曾尝试应用keyframes(关键帧)和animation属性,但动画直接完成,未呈现过渡效果,尽管transition(过渡)属性设置正确。
下方示例中的动画仅在悬停时触发,如何修改使其在页面加载时触发?预期效果是动画在页面加载时触发,且仅当元素滚动到视图范围内时执行。

原代码

CSS

main {
  padding: 5rem 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

main .carousel {
  max-height: 500px;
  overflow: hidden;
}

main .carousel figure {
  height: 500px;
  background: url("https://res.cloudinary.com/dqjhiewf1/image/upload/v1666092821/fullPagePrint/portfolio_fullpage_kg2c1w.png");
  width: 550px;
  background-size: cover;
  background-position: top center;
  transform: perspective(1000px) rotateY(-13deg) rotateX(5deg) rotate(1deg) scaleY(0.9) scaleX(0.95) translate(-3%) translateY(-3%);
  transition: all 8.5s ease, transform 0.5s ease;
}

main .carousel figure:hover {
  background-position: bottom center;
  cursor: pointer;
  overflow: auto;
  transform: perspective(1000px) rotateY(0) rotateX(0) rotate(0) scale(1) translate(0) translateY(0);
  transition: all 8.5s ease, transform 0.5s ease;
}

HTML

<main>
  <a href="https://axie-infinity-lp.vercel.app" target="_blank">
    <div class="carousel">
      <figure></figure>
    </div>
  </a>
</main>
解决方案

要实现元素进入视图时自动执行动画,需要结合CSS关键帧动画和Intersection Observer API,具体修改如下:

1. 定义CSS关键帧动画

把hover状态的变化转换成关键帧,明确动画的起始和结束状态:

@keyframes revealImage {
  0% {
    background-position: top center;
    transform: perspective(1000px) rotateY(-13deg) rotateX(5deg) rotate(1deg) scaleY(0.9) scaleX(0.95) translate(-3%) translateY(-3%);
  }
  100% {
    background-position: bottom center;
    transform: perspective(1000px) rotateY(0) rotateX(0) rotate(0) scale(1) translate(0) translateY(0);
  }
}

2. 修改元素基础样式与动画触发规则

移除hover伪类样式,新增一个animate类用于触发动画,同时保留元素的交互属性:

main .carousel figure {
  height: 500px;
  background: url("https://res.cloudinary.com/dqjhiewf1/image/upload/v1666092821/fullPagePrint/portfolio_fullpage_kg2c1w.png");
  width: 550px;
  background-size: cover;
  background-position: top center;
  transform: perspective(1000px) rotateY(-13deg) rotateX(5deg) rotate(1deg) scaleY(0.9) scaleX(0.95) translate(-3%) translateY(-3%);
  cursor: pointer;
  overflow: auto;
}

/* 添加动画触发类,forwards 让元素保持动画结束后的状态 */
main .carousel figure.animate {
  animation: revealImage 8.5s ease forwards;
}

3. 用Intersection Observer监听视图进入事件

添加JS代码,当元素滚动到视图范围内时,自动为其添加animate类触发动画:

// 获取目标元素
const targetFigure = document.querySelector('main .carousel figure');

// 创建观察者实例,设置触发条件
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // 元素进入视图,启动动画
      entry.target.classList.add('animate');
      // 仅执行一次,停止观察当前元素
      observer.unobserve(entry.target);
    }
  });
}, {
  threshold: 0.1 // 元素10%进入视图时触发动画
});

// 开始监听目标元素
observer.observe(targetFigure);

完整修改后代码

CSS

main {
  padding: 5rem 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

main .carousel {
  max-height: 500px;
  overflow: hidden;
}

@keyframes revealImage {
  0% {
    background-position: top center;
    transform: perspective(1000px) rotateY(-13deg) rotateX(5deg) rotate(1deg) scaleY(0.9) scaleX(0.95) translate(-3%) translateY(-3%);
  }
  100% {
    background-position: bottom center;
    transform: perspective(1000px) rotateY(0) rotateX(0) rotate(0) scale(1) translate(0) translateY(0);
  }
}

main .carousel figure {
  height: 500px;
  background: url("https://res.cloudinary.com/dqjhiewf1/image/upload/v1666092821/fullPagePrint/portfolio_fullpage_kg2c1w.png");
  width: 550px;
  background-size: cover;
  background-position: top center;
  transform: perspective(1000px) rotateY(-13deg) rotateX(5deg) rotate(1deg) scaleY(0.9) scaleX(0.95) translate(-3%) translateY(-3%);
  cursor: pointer;
  overflow: auto;
}

main .carousel figure.animate {
  animation: revealImage 8.5s ease forwards;
}

HTML

<main>
  <a href="https://axie-infinity-lp.vercel.app" target="_blank">
    <div class="carousel">
      <figure></figure>
    </div>
  </a>
</main>

JavaScript

const targetFigure = document.querySelector('main .carousel figure');

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('animate');
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.1 });

observer.observe(targetFigure);

说明

  • 关键帧动画明确了状态过渡的全过程,forwards属性确保动画结束后元素保持最终状态。
  • Intersection Observer API相比传统滚动事件更高效,threshold参数可灵活调整动画触发的时机。
  • 通过类触发动画的方式,确保动画仅在元素进入视图时执行一次,符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:30:21