在前端开发中,九宫格布局不仅常用于图像展示,还能用于交互式动画效果。本篇博客将详细拆解一个 九宫格拼图动画,实现鼠标悬停时拼图从散开状态合并成完整图片的效果,同时深入讲解 CSS 核心属性及拓展知识,帮助你掌握更多 CSS 动画技巧。
一、效果展示
效果如下:
-
默认状态:九宫格拼图略微散开,产生"拼图碎片"的感觉
-
鼠标悬停:拼图块合并为完整图片,动画平滑过渡
✅ 适用场景:个人作品集、网页 Banner 动画、图片交互效果等

二、完整代码
html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>九宫格拼图动画</title>
<style>
/* 页面布局 */
body{
background:linear-gradient(200deg,#fdd6bd,#f794a4);
height:100vh;
display:flex;
justify-content:center;
align-items:center;
}
/* 九宫格容器 */
.grid{
width:360px;
height:360px;
display:grid;
grid-template-columns:repeat(3,1fr);
grid-template-rows:repeat(3,1fr);
/* gap: 8px; 可替代 transform 散开效果(详解见下文) */
/* transition:gap 0.6s cubic-bezier(.4,0,.2,1); */
}
/* 拼图块样式 */
.item{
background-image:url("https://picsum.photos/600");
background-size:360px 360px;/* 保持背景图大小与容器一致 */
transition:transform 0.6s cubic-bezier(.4,0,.2,1);
box-shadow: inset 0 0 0 1px #fff; /* 内阴影模拟分割线 */
}
/* 设置每个拼图块的背景位置,实现切图 */
.item:nth-child(1){background-position:0 0;}
.item:nth-child(2){background-position:-120px 0;}
.item:nth-child(3){background-position:-240px 0;}
.item:nth-child(4){background-position:0 -120px;}
.item:nth-child(5){background-position:-120px -120px;}
.item:nth-child(6){background-position:-240px -120px;}
.item:nth-child(7){background-position:0 -240px;}
.item:nth-child(8){background-position:-120px -240px;}
.item:nth-child(9){background-position:-240px -240px;}
/* 初始散开效果 */
.item:nth-child(1){transform:translate(-8px,-8px);}
.item:nth-child(2){transform:translate(0,-8px);}
.item:nth-child(3){transform:translate(8px,-8px);}
.item:nth-child(4){transform:translate(-8px,0);}
.item:nth-child(5){transform:translate(0,0);}
.item:nth-child(6){transform:translate(8px,0);}
.item:nth-child(7){transform:translate(-8px,8px);}
.item:nth-child(8){transform:translate(0,8px);}
.item:nth-child(9){transform:translate(8px,8px);}
/* 鼠标悬停时拼图合并 */
/*.grid:hover{
gap:0;
}*/
.grid:hover .item{
transform:translate(0,0);
box-shadow:none;/* 移除阴影 */
}
</style>
</head>
<body>
<div class="grid">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
</html>
三、实现原理解析
1. 核心布局------CSS Grid
css
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
-
display: grid:开启网格布局 -
grid-template-columns/rows:设置 3 列 3 行 -
1fr表示每列/行占用相等的空间
✅ 拓展知识:
-
grid-gap/gap:设置网格间隙 -
grid-auto-flow:控制自动布局方向(行/列) -
Grid 可以轻松实现响应式布局,配合
minmax()可以自适应屏幕
2. 切图效果------background-position + background-size
每个 .item 的背景图是同一张大图,通过 background-position 调整显示区域:
css
.item:nth-child(2){ background-position: -120px 0; }
-
横向移动
-120px,只显示图片的第二块 -
background-size: 360px 360px;保证每块显示完整图片的一部分
✅ 拓展:
-
可用
background-repeat: no-repeat防止重复 -
background-clip可以控制图片显示区域 -
使用 CSS sprite 技术,减少请求次数
3. 散开动画------transform + transition
css
.item:nth-child(1){ transform: translate(-8px, -8px); }
-
transform: translate(x, y)平移元素 -
transition: transform 0.6s cubic-bezier(.4,0,.2,1)控制平移动画,贝塞尔曲线可自定义动画节奏
✅ 拓展:
-
translateX()/translateY()可单独控制方向 -
scale()、rotate()可结合 transform 实现更多动画 -
cubic-bezier()拓展动画节奏,自定义缓动效果
💡 散开效果实现方式对比
在本示例中,我们使用 transform: translate(...) 来实现拼图块的散开动画,但实际上也可以通过 gap 来实现类似视觉效果。
方法 1:使用 transform: translate(...)
css
.item:nth-child(1){ transform: translate(-8px, -8px); }
.item:nth-child(2){ transform: translate(0, -8px); }
.item:nth-child(3){ transform: translate(8px, -8px); }
效果:
-
拼图块可以 自由散开任意方向和距离
-
可以和
transition动画结合,实现平滑过渡 -
鼠标悬停时可以使用
transform: translate(0,0)来回合并
特点:
| 特性 | 描述 |
|---|---|
| 动画效果 | transform 动画 GPU 加速,平滑且性能高 |
| 灵活性 | 可随意调整每个块的散开方向和距离 |
| 定制能力 | 可以实现旋转、缩放、立体感等复杂动画效果 |
| 复杂度 | 需要给每个块写 transform,代码稍多 |
方法 2:使用 gap 设置网格间距
css
.grid {
gap: 8px; /* 网格间距 */
}
效果:
-
九宫格每个块之间自动有 8px 间距
-
不需要给每个
.item额外写transform: translate(...) -
实现起来简单,CSS 更干净
特点:
| 特性 | 描述 |
|---|---|
| 简洁性 | 只用一条 gap 就能实现散开 |
| 动画灵活性 | gap 的动画不如 transform 平滑(大多数浏览器不支持 gap 的过渡动画) |
| 响应式 | gap 自动适应网格布局,和布局元素保持一致 |
方法对比总结
| 比较维度 | gap: 8px | transform: translate(...) |
|---|---|---|
| 实现复杂度 | 简单 | 较复杂,需要写每个块 |
| 动画能力 | 低,大部分浏览器不支持 gap 动画 | 高,可与 transition / keyframes 平滑动画 |
| 灵活性 | 低,只能四周等距 | 高,可自由控制每块方向和距离 |
| 性能 | CPU 渲染,适合静态布局 | GPU 渲染,适合动态动画 |
| 适用场景 | 网格布局、静态间距 | 动画交互、散开合并、拼图效果 |
✅ 选择建议:
-
静态布局 (只是想让格子间距看起来散开一点):直接用
gap,简单高效。 -
交互动画 (拼图合并、旋转、缩放、悬停效果):用
transform,平滑且可控。 -
混合场景 :可以同时用
gap+transform,基础间距用 gap,微调动画用 transform。
4. 悬停合并------伪类 + 动画过渡
css
.grid:hover .item{
transform: translate(0,0);
box-shadow: none;
}
-
:hover触发状态 -
设置
transform: translate(0,0)将散开的拼图块回到原位 -
transition自动平滑过渡
✅ 拓展:
-
可结合
scale()或rotate()实现缩放或翻转动画 -
:hover也可用于触发颜色渐变、阴影、旋转等效果 -
可与 JS 动态控制
transform实现拖拽或点击动画
四、优化与扩展建议
-
响应式九宫格
- 使用
max-width、minmax()和%来代替固定像素
- 使用
-
增加点击翻转效果
- 使用
transform: rotateY(180deg)或rotateX()
- 使用
-
可拓展到 n*n 拼图
- 用循环生成
.item,动态计算background-position
- 用循环生成
五、总结
通过本篇教程,你学会了:
-
使用 CSS Grid 构建九宫格布局
-
利用 background-position 实现拼图切割
-
使用 transform + transition 创建散开到合并动画
-
对比 gap 与 transform 散开方式,掌握选择场景
-
通过 :hover 控制交互效果
这是一个既美观又实用的前端动画案例,适合做网页作品集、交互式 Banner 或拼图小游戏。