前端八股CSS(2)---动画的实现方式

目录


一、核心区别速览

对比维度 transition animation
中文名 过渡动画 关键帧动画
定义方式 起点 → 终点 可定义多个关键帧(0% → 50% → 100%)
触发条件 ✅ 需要(hover、click、class变化) ❌ 不需要(页面加载可自动执行)
循环播放 ❌ 不支持(需要JS配合) ✅ 支持(infinite无限循环)
中间状态 自动计算补间 可精确控制每一帧
适用场景 简单、一次性动画 复杂、连续、自动播放动画

二、transition(过渡动画)

2.1 一句话定义

让元素从一个样式状态,平滑过渡到另一个样式状态。

2.2 语法

css 复制代码
/* 完整写法 */
transition: 属性名 时长 运动曲线 延迟时间;

/* 示例 */
.box {
  width: 100px;
  height: 100px;
  background: red;
  
  /* 所有属性变化都过渡,时长0.5秒,缓动曲线,不延迟 */
  transition: all 0.5s ease 0s;
  
  /* 或者分开写 */
  transition-property: width, height;     /* 要过渡的属性 */
  transition-duration: 0.5s;              /* 过渡时长 */
  transition-timing-function: ease;       /* 运动曲线 */
  transition-delay: 0s;                   /* 延迟时间 */
}

.box:hover {
  width: 200px;
  height: 200px;
  background: blue;
}

2.3 运动曲线(timing-function)

效果 说明
ease 慢→快→慢 默认值,最自然
linear 匀速 机械感
ease-in 慢→快 加速
ease-out 快→慢 减速
ease-in-out 慢→快→慢 与ease类似但更平滑
cubic-bezier(n,n,n,n) 自定义 贝塞尔曲线
css 复制代码
/* 自定义贝塞尔曲线 */
.box {
  transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  /* 可以做出弹簧效果 */
}

2.4 适用场景

css 复制代码
/* 1. hover 按钮变色 */
.btn {
  background: blue;
  transition: background 0.3s ease;
}
.btn:hover {
  background: red;
}

/* 2. 菜单展开/收起 */
.menu {
  height: 0;
  opacity: 0;
  transition: all 0.3s ease;
}
.menu.open {
  height: 200px;
  opacity: 1;
}

/* 3. 卡片悬停放大 */
.card {
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
  transform: translateY(-10px);
  box-shadow: 0 10px 20px rgba(0,0,0,0.2);
}

三、animation + @keyframes(关键帧动画)

3.1 一句话定义

自己定义多个关键状态,让元素自动按顺序播放的复杂动画。

3.2 两部分组成

css 复制代码
/* 第1步:定义关键帧 */
@keyframes 动画名称 {
  0% { 
    /* 起始样式 */
    transform: translateX(0);
    opacity: 0;
  }
  50% {
    /* 中间样式 */
    transform: translateX(50px);
    opacity: 0.5;
  }
  100% {
    /* 结束样式 */
    transform: translateX(100px);
    opacity: 1;
  }
}

/* 第2步:应用动画 */
.box {
  animation-name: 动画名称;           /* 关键帧名称 */
  animation-duration: 2s;           /* 动画时长 */
  animation-timing-function: ease;  /* 运动曲线 */
  animation-delay: 0s;              /* 延迟时间 */
  animation-iteration-count: 1;     /* 播放次数(infinite无限) */
  animation-direction: normal;      /* 播放方向 */
  animation-fill-mode: forwards;    /* 动画结束后保持最后一帧 */
  animation-play-state: running;    /* 播放状态 */
}

/* 简写(推荐) */
/* animation: 名称 时长 曲线 延迟 次数 方向 填充模式; */
.box {
  animation: slideIn 0.5s ease 0s 1 normal forwards;
}

3.3 关键属性详解

属性 可选值 说明
animation-name 自定义名称 对应@keyframes的名称
animation-duration 时间(s/ms) 动画时长
animation-timing-function ease/linear/step等 运动曲线
animation-delay 时间(s/ms) 延迟多久开始
animation-iteration-count 数字 / infinite 播放次数
animation-direction normal / reverse / alternate 播放方向
animation-fill-mode none / forwards / backwards 结束后状态
animation-play-state running / paused 播放/暂停

3.4 适用场景

css 复制代码
/* 1. 加载动画(无限循环) */
@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
.loader {
  animation: spin 1s linear infinite;
}

/* 2. 入场动画(自动执行) */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.page-enter {
  animation: fadeInUp 0.5s ease forwards;
}

/* 3. 复杂多阶段动画 */
@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-30px); }
  70% { transform: translateY(-10px); }
}
.bounce {
  animation: bounce 1s ease infinite;
}

/* 4. 呼吸灯效果 */
@keyframes pulse {
  0% { opacity: 0.6; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.05); }
  100% { opacity: 0.6; transform: scale(1); }
}
.pulse {
  animation: pulse 2s ease infinite;
}

四、transition vs animation 详细对比

对比维度 transition animation
触发方式 需要触发(hover/click/class) 自动触发(页面加载即执行)
关键帧 只有起点和终点 可定义多个关键帧(0%-100%)
循环播放 ❌ 不支持 ✅ 支持(infinite)
反向播放 ❌ 需要重新触发 ✅ 支持(alternate/reverse)
暂停/播放 ❌ 不支持 ✅ 支持(animation-play-state)
结束后状态 回到起点 可保持终点(forwards)
代码量
控制精度
适用场景 简单交互动画 复杂连续动画

五、实战示例

示例1:按钮悬停效果(transition)

css 复制代码
.btn {
  padding: 10px 20px;
  background: #3498db;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  
  /* 多个属性分别设置过渡 */
  transition: 
    background 0.3s ease,
    transform 0.2s ease,
    box-shadow 0.3s ease;
}

.btn:hover {
  background: #2980b9;
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}

.btn:active {
  transform: translateY(0);
}

示例2:骨架屏加载(animation)

css 复制代码
@keyframes shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

.skeleton {
  background: linear-gradient(
    90deg,
    #f0f0f0 25%,
    #e0e0e0 50%,
    #f0f0f0 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

示例3:通知消息入场/出场

css 复制代码
/* 入场动画 */
@keyframes slideInRight {
  from {
    opacity: 0;
    transform: translateX(100%);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* 出场动画 */
@keyframes slideOutRight {
  from {
    opacity: 1;
    transform: translateX(0);
  }
  to {
    opacity: 0;
    transform: translateX(100%);
  }
}

.notification-enter {
  animation: slideInRight 0.3s ease forwards;
}

.notification-exit {
  animation: slideOutRight 0.3s ease forwards;
}

六、面试高频问题

Q1:transition 和 animation 的区别?

答:

  1. 触发方式:transition 需要触发(hover/click/class变化),animation 可以自动执行

  2. 关键帧:transition 只有起点和终点,animation 可以定义多个关键帧

  3. 循环播放:transition 不支持循环,animation 支持 infinite 无限循环

  4. 控制能力:animation 可以控制播放方向、暂停、结束后状态等

简单来说:transition 适合简单的交互动画,animation 适合复杂的自动播放动画。

Q2:如何用 transition 实现循环动画?

答:

transition 本身不支持循环,可以通过 JS 添加/移除 class 来模拟循环。但更推荐用 animation。

Q3:animation 的 fill-mode 有什么作用?

答:

animation-fill-mode 决定动画结束后元素的样式:

  • none(默认):回到动画前样式

  • forwards:保持动画最后一帧样式

  • backwards:保持动画第一帧样式

  • both:同时应用 forwards 和 backwards

相关推荐
GreenTea4 小时前
从 Claw-Code 看 AI 驱动的大型项目开发:2 人 + 10 个自治 Agent 如何产出 48K 行 Rust 代码
前端·人工智能·后端
渣渣xiong4 小时前
从零开始:前端转型AI agent直到就业第五天-第十一天
前端·人工智能
布局呆星4 小时前
Vue3 | 组件通信学习小结
前端·vue.js
C澒4 小时前
IntelliPro 企业级产研协作平台:前端智能生产模块设计与落地
前端·ai编程
OpenTiny社区6 小时前
重磅预告|OpenTiny 亮相 QCon 北京,共话生成式 UI 最新技术思考
前端·开源·ai编程
前端老实人灬6 小时前
web前端面试题
前端
Moment6 小时前
AI 全栈指南:NestJs 中的 Service Provider 和 Module
前端·后端·面试
IT_陈寒6 小时前
为什么我的JavaScript异步回调总是乱序执行?
前端·人工智能·后端