纯CSS可实现沙漏翻转动画,核心是用transform: rotateY()配合两个三角形的显隐切换与3D旋转;总周期固定(如4s),翻转发生在中点时刻,需JS绑定真实倒计时逻辑。

用纯 CSS 实现沙漏倒计时翻转动画,核心是利用 transform: rotateY() 模拟沙粒“翻转下落”的视觉效果,并通过 @keyframes 控制两个三角形(上半沙漏 + 下半沙漏)的交替显隐与旋转节奏。不需要 JS,但需注意:CSS 无法真正“倒计时”,它只能做固定时长的循环动画;若要绑定真实倒计时逻辑(如 60 秒),仍需 JS 控制类名或自定义属性,CSS 只负责视觉表现。
1. 结构:用两个三角形拼出沙漏轮廓
沙漏本质是对称的双锥体。我们用两个等腰三角形(分别代表上半空腔和下半积沙区),通过伪元素或两个 div 构建,共用一个容器控制翻转轴心:
- 外层容器设
perspective和transform-style: preserve-3d,让 3D 变换生效 - 上三角(
.top)初始显示,朝下;下三角(.bottom)初始隐藏,朝上 - 翻转时,上三角绕 Y 轴旋转 180° 隐藏,下三角同步旋转 180° 显现,形成“沙子流完→翻转→重新开始”的错觉
2. 样式:关键在 3D 旋转与层级切换
以下是最简可用的 CSS 片段(假设总周期 4s,翻转发生在 2s 时刻):
.hourglass {
width: 80px;
height: 120px;
perspective: 200px;
transform-style: preserve-3d;
}
.top, .bottom {
position: absolute;
width: 0;
height: 0;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 60px solid #e0c9a6; /* 沙色 */
transform-style: preserve-3d;
}
.top {
border-bottom-color: #d4bda0;
top: 0;
}
.bottom {
border-top: 60px solid #e0c9a6;
border-bottom: none;
top: 60px;
transform: rotateX(180deg); /* 初始倒置,隐藏沙粒 */
}
<p>/<em> 翻转动画 </em>/
@keyframes flip {
0% {
transform: rotateY(0);
}
49% {
transform: rotateY(0);
}
50% {
transform: rotateY(180deg);
}
100% {
transform: rotateY(180deg);
}
}
.hourglass {
animation: flip 4s infinite linear;
}
.top {
animation: showTop 4s infinite linear;
}
.bottom {
animation: showBottom 4s infinite linear;
}</p><p>@keyframes showTop {
0%, 49% { opacity: 1; }
50%, 100% { opacity: 0; }
}
@keyframes showBottom {
0%, 49% { opacity: 0; }
50%, 100% { opacity: 1; }
}3. 增强真实感:加沙粒动效(可选)
纯三角太抽象?可以叠加一层浮动小圆点模拟沙粒下落:
立即学习“前端免费学习笔记(深入)”;
- 用
::before或额外div生成 10–15 个span,绝对定位在沙漏中部区域 - 每个沙粒设不同
animation-delay和animation-duration,沿 Y 轴做translateY下落 + 微小左右摇摆 - 配合主翻转动画,在 0–2s 让沙粒从上往下掉;2–4s 主容器翻转后,沙粒重置位置并反向“上升”(视觉上就是新沙漏开始流)
4. 绑定真实倒计时(JS 辅助)
如果需要精确控制剩余时间(比如 30 秒倒计时),CSS 本身做不到动态时长,但可以这样协同:
- JS 计算剩余秒数,写入容器的
style.setProperty('--time-left', seconds) - CSS 中用
animation-duration: calc(var(--time-left) * 1s)(仅支持部分现代浏览器) - 更兼容的做法:JS 在倒计时结束时切换类名(如
.running → .flipped),CSS 定义两套动画状态,用transition衔接翻转
不复杂但容易忽略:确保父容器有明确宽高、开启 3D 渲染上下文、避免被其他 overflow: hidden 截断。调试时可临时加 outline: 1px solid red 查看旋转轴心是否居中。


















