- 教程
- 文档
【免费下载链接】30-seconds-of-code
Coding articles to level up your development skills
缩放进出动画(zoom in zoom out)是一种极为常见且优雅的 CSS 动效,常被用于吸引用户注意力的按钮、加载提示、营销 Banner 或品牌 Logo 等场景。本文以 30-seconds-of-code 仓库中的 zoomin-zoomout-animation.md 为骨架,完整讲解如何用@keyframes定义一个三步缩放动画、如何通过animation简写属性控制其时长、缓动与循环次数,并给出scale属性与transform: scale()两种写法的兼容性方案。读完后你将能直接复制一套可运行的缩放动画,并掌握调整缓动、延迟与循环方式的进阶技巧。
三步动画的核心原理:@keyframes 与 scale
一个缩放进出动画本质上是一个三步动画,可以直接用@keyframes定义:
- 起始点(
0%):元素保持原始尺寸,即scale: 100%; - 中间点(
50%):元素放大到更大尺寸,例如scale: 150%; - 结束点(
100%):元素回到原始尺寸,即scale: 100%。
动画从原始尺寸放大到 150%,再回落到原始尺寸,视觉上就产生了"先放大、再缩小"的缩放循环。这就是缩放进出动画的全部秘密——没有复杂的位移,也没有多段关键帧堆叠,只需三个关键帧即可。
[!TIP]
这里使用的是相对较新的
scale独立属性(注意它直接写scale: 150%,使用的是百分比)。相比传统的transform,scale属性可以独立于transform存在,后续还可以与其他变换组合使用,不会互相覆盖。
应用动画:animation 简写属性与完整代码
定义好@keyframes之后,还需要用animation属性把它应用到元素上。原文档中的完整示例如下:
.zoom-in-out-element { animation: zoom-in-zoom-out 1s ease infinite; } @keyframes zoom-in-zoom-out { 0% { scale: 100%; } 50% { scale: 150%; } 100% { scale: 100%; } }animation简写属性zoom-in-zoom-out 1s ease infinite依次对应:
| 简写片段 | 含义 | 说明 |
|---|---|---|
zoom-in-zoom-out | animation-name | 引用下方@keyframes定义的动画名称 |
1s | animation-duration | 单次动画持续 1 秒,可按需调整为0.5s、2s等 |
ease | animation-timing-function | 缓动函数,控制放大/缩小过程中的速度曲线 |
infinite | animation-iteration-count | 无限循环播放;若只播 2 次可改为2 |
如果你偏好长写形式,效果完全等价:
.zoom-in-out-element { animation-name: zoom-in-zoom-out; animation-duration: 1s; animation-timing-function: ease; animation-iteration-count: infinite; }这种长写拆分的方式在仓库的 alternating-text.md 中也有体现——该文章把animation-name、animation-duration、animation-iteration-count、animation-timing-function四个属性逐一写出,便于理解每个属性的独立作用。
[!NOTE]
原文档指出,本示例使用的时长
1s、缓动ease与无限循环都只是默认建议,你可以根据自己的设计需求自由调整这几个值。
兼容性方案:scale 属性与 transform: scale() 互换
原文档特别给出了一个兼容性提醒:scale是相对较新的 CSS 属性。如果你担心旧浏览器兼容性,可以无缝替换为传统的transform写法:
.zoom-in-out-element { animation: zoom-in-zoom-out 1s ease infinite; } @keyframes zoom-in-zoom-out { 0% { transform: scale(1, 1); } 50% { transform: scale(1.5, 1.5); } 100% { transform: scale(1, 1); } }两种写法的对应关系非常直观:
scale: 100%↔transform: scale(1, 1)scale: 150%↔transform: scale(1.5, 1.5)
scale(1, 1)表示在 X 轴、Y 轴上均保持 1 倍(原始大小),scale(1.5, 1.5)表示两个轴都放大到 1.5 倍。这种"新属性 ↔ 传统 transform"的互换思路在仓库其他文章中也有体现,例如 button-hover-transitions.md 中就提示可以将悬停放大效果里的transform: scale(1.1)替换为scale: 110%。
进阶:让缩放动画更精致的三个技巧
原文档只给了基础版本,结合仓库中同属 CSS 动画系列的其他片段,还可以快速升级这个效果。
1. 更换缓动函数,让动画更有质感
ease是默认缓动,适用于大多数场景。若希望放大和缩回的过程节奏更统一,可以改用ease-in-out:
.zoom-in-out-element { animation: zoom-in-zoom-out 1s ease-in-out infinite; }更进阶的做法是使用cubic-bezier()自定义贝塞尔曲线。仓库中的 easing-variables.md 提供了整套缓动变量,例如--ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1)。你可以把缓动抽成变量后应用到缩放动画上:
:root { --ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1); } .zoom-in-out-element { animation: zoom-in-zoom-out 1s var(--ease-in-out-cubic) infinite; }2. 用 animation-delay 制造交错效果
如果页面上有多个元素需要依次缩放(例如多个卡片、多个图标),可以为每个元素设置不同的animation-delay,让动画依次启动而不是同时启动。这一技巧在 loaders.md 的弹跳加载器(bouncing loader)中得到了完整示范——三个小球分别使用animation-delay: 0s、0.2s、0.4s产生依次弹跳的节奏:
.zoom-item:nth-child(1) { animation: zoom-in-zoom-out 1s ease infinite 0s; } .zoom-item:nth-child(2) { animation: zoom-in-zoom-out 1s ease infinite 0.2s; } .zoom-item:nth-child(3) { animation: zoom-in-zoom-out 1s ease infinite 0.4s; }3. 用 animation-direction 实现两段式缩放
如果不需要"放大再缩小"的完整循环,只想让元素在两个状态之间往复,可以只用两个关键帧,并配合animation-direction: alternate。loaders.md中的弹跳球动画正是用0.6s infinite alternate在两个关键帧之间往返。缩放的简化版本如下:
.zoom-pulse { animation: zoom-pulse 1s ease-in-out infinite alternate; } @keyframes zoom-pulse { from { scale: 100%; } to { scale: 120%; } }4. 控制循环次数:有限次动画
并不是所有场景都需要无限循环。原文档示例使用了infinite,但在"用户输入错误时抖动提示"这类场景中,动画通常只应播放有限次数。仓库中的 shake-invalid-input.md 展示了animation: shake 0.2s ease-in-out 0s 2的写法——第 4 个位置是animation-delay: 0s,最后一个数字2表示只播放 2 次。缩放动画同样可以这样控制,例如"放大提醒后停止":
.zoom-alert { animation: zoom-in-zoom-out 1s ease 0s 2; }实战建议与可访问性注意
- 优先使用
scale或transform做缩放:缩放属于合成器(compositor)友好的变换类属性,相比逐帧改变width、height或margin,动画过程通常更流畅。仓库中 loaders.md 在讲解弹跳球时也特别提到使用transform: translate3d()以获得更好的动画性能,思路一致。 - 尊重用户的减弱动效偏好:无限循环的缩放动画对部分用户(如前庭功能障碍者)可能造成不适。可以考虑用
prefers-reduced-motion媒体查询在系统开启"减少动态效果"时关闭动画:
@media (prefers-reduced-motion: reduce) { .zoom-in-out-element { animation: none; } }- 控制动画规模与频率:持续的缩放动效适合按钮、加载状态或短暂的品牌展示;若页面中多个元素同时无限缩放,容易分散用户注意力,建议按上文的
animation-delay交错或改用有限次数。
在 30-seconds-of-code 中的位置与延伸阅读
本片段位于 content/snippets/css/s/zoomin-zoomout-animation.md,归属于 CSS 动画集合。仓库中 content/collections/css/animation.yaml 通过tagMatcher: animation将本片段归入 "CSS Animations" 集合,你可以在这个集合下继续探索更多动画主题:
- loaders.md:弹跳球、脉冲涟漪、甜甜圈加载器,覆盖
animation-delay、animation-direction与transform的更多组合; - alternating-text.md:通过
animationiteration事件驱动文字轮换,展示animation长写属性与 JS 配合的用法; - shake-invalid-input.md:结合
:invalid伪类与有限次数动画的反馈动效; - button-hover-transitions.md:
scale属性与transform: scale()互换的悬停场景; - easing-variables.md:一整套
cubic-bezier()缓动变量,可直接用于自定义缩放节奏。
以上就是用 CSS 实现缩放进出动画的完整方案:三步关键帧定义核心动作,animation简写属性控制节奏,scale/transform双写法兼顾新旧浏览器,再配合缓动、延迟与方向控制即可轻松适配各种交互场景。
- 教程
- 文档
【免费下载链接】30-seconds-of-code
Coding articles to level up your development skills
相关推荐
freeCodeCamp 实战:用 CSS @keyframes 与 animation 属性创建颜色渐变动画
freeCodeCamp 实战:用 CSS @keyframes 与 animation 属性创建颜色渐变动画 本篇基于 freeCodeCamp 课程「App
前端后端教育d3 interpolateZoom 平滑缩放插值器:d3-zoom 动画轨迹与时长控制的原理与实践
d3 interpolateZoom 平滑缩放插值器:d3 zoom 动画轨迹与时长控制的原理与实践 d3.interpolateZoom 是 d3 inter
前端数据可视化图表库NgKeyboardTracker源码探秘:iOS键盘跟踪实现原理
NgKeyboardTracker源码探秘:iOS键盘跟踪实现原理 NgKeyboardTracker是一款专为iOS应用打造的Objective C库,专注于
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考