动效库
先叫出动作。
别再说「让它动起来」。叫出动作名,复制 Prompt,看它真动起来。
入场与退场
Item
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.fade-up-item {
animation-name: fadeUp;
animation-duration: var(--anim-duration, 2.2s);
animation-timing-function: var(--anim-easing, cubic-bezier(0.16, 1, 0.3, 1));
padding: 16px 22px;
border-radius: 12px;
background: var(--surface, #fff);
border: 1px solid var(--border, #e6e7ec);
font: 600 14px/1 'Plus Jakarta Sans', system-ui, sans-serif;
color: var(--ink, #1a1c22);
}
@keyframes fadeUp {
0% { opacity: 0; transform: translateY(26px); }
30%, 100% { opacity: 1; transform: translateY(0); }
} - First
- First
- First
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.stagger { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; width: min(220px, 100%); }
.stagger .anim-el {
animation-name: fadeUp;
animation-duration: var(--anim-duration, 2.6s);
animation-timing-function: var(--anim-easing, cubic-bezier(0.16, 1, 0.3, 1));
padding: 14px 18px;
border-radius: 10px;
background: var(--surface, #fff);
border: 1px solid var(--border, #e6e7ec);
font: 600 14px/1 'Plus Jakarta Sans', system-ui, sans-serif;
color: var(--ink, #1a1c22);
}
.stagger .anim-el:nth-child(2) { animation-delay: 0.14s; }
.stagger .anim-el:nth-child(3) { animation-delay: 0.28s; }
@keyframes fadeUp {
0% { opacity: 0; transform: translateY(26px); }
30%, 100% { opacity: 1; transform: translateY(0); }
} 悬停与焦点
Card
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.hover-lift-card {
animation-name: lift;
animation-duration: var(--anim-duration, 2.4s);
animation-timing-function: var(--anim-easing, ease-in-out);
width: min(200px, 100%);
padding: 18px;
border-radius: 14px;
background: var(--surface, #fff);
border: 1px solid var(--border, #e6e7ec);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
font: 600 14px/1.3 'Plus Jakarta Sans', system-ui, sans-serif;
color: var(--ink, #1a1c22);
}
@keyframes lift {
0%, 60%, 100% { transform: translateY(0); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }
30% { transform: translateY(-12px); box-shadow: 0 20px 34px -14px rgba(0, 0, 0, 0.28); }
} 按钮按压 查看详情 复制 Prompt 复制 CSS .anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.button-press-btn {
animation-name: press;
animation-duration: var(--anim-duration, 1.6s);
animation-timing-function: var(--anim-easing, ease-in-out);
border: 0;
border-radius: 12px;
padding: 14px 26px;
font: 600 15px/1 'Plus Jakarta Sans', system-ui, sans-serif;
color: #fff;
background: var(--anim-accent);
cursor: pointer;
}
@keyframes press {
0%, 100% { transform: scale(1); }
40%, 60% { transform: scale(0.94); }
} 按钮涟漪 查看详情 复制 Prompt 复制 CSS .anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.ripple-btn {
position: relative;
overflow: hidden;
border: 0;
border-radius: 12px;
padding: 14px 26px;
font: 600 15px/1 'Plus Jakarta Sans', system-ui, sans-serif;
color: #fff;
background: var(--anim-accent);
cursor: pointer;
}
.ripple-btn .ripple-dot {
position: absolute;
left: 50%;
top: 50%;
width: 12px;
height: 12px;
margin: -6px 0 0 -6px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.6);
animation-name: ripple;
animation-duration: var(--anim-duration, 1.8s);
animation-timing-function: var(--anim-easing, ease-out);
}
@keyframes ripple {
0% { transform: scale(1); opacity: 0.55; }
100% { transform: scale(16); opacity: 0; }
} 加载与进度
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.skel-wrap { width: min(220px, 100%); display: grid; gap: 12px; }
.skel-line {
height: 16px;
border-radius: 8px;
background: linear-gradient(90deg, #e7e8ee 25%, #f6f7fa 37%, #e7e8ee 63%);
background-size: 200% 100%;
animation-name: shimmer;
animation-duration: var(--anim-duration, 1.4s);
animation-timing-function: var(--anim-easing, ease-in-out);
}
.skel-line:nth-child(2) { width: 80%; }
.skel-line:nth-child(3) { width: 60%; }
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
} .anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.dots { display: flex; gap: 12px; }
.dots .dot {
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--anim-accent);
animation-name: dotBounce;
animation-duration: var(--anim-duration, 1.2s);
animation-timing-function: var(--anim-easing, ease-in-out);
}
.dots .dot:nth-child(2) { animation-delay: 0.15s; }
.dots .dot:nth-child(3) { animation-delay: 0.3s; }
@keyframes dotBounce {
0%, 100% { transform: translateY(0); opacity: 0.5; }
50% { transform: translateY(-9px); opacity: 1; }
} Loading…
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.prog { width: min(240px, 100%); }
.prog-track {
height: 10px;
border-radius: 999px;
background: color-mix(in srgb, var(--anim-accent) 16%, #e7e8ee);
overflow: hidden;
}
.prog-fill {
height: 100%;
border-radius: 999px;
background: var(--anim-accent);
animation-name: fill;
animation-duration: var(--anim-duration, 2.2s);
animation-timing-function: var(--anim-easing, cubic-bezier(0.16, 1, 0.3, 1));
}
.prog-label { margin-top: 10px; font: 500 12px/1 'IBM Plex Mono', monospace; color: var(--mute, #6b6f7a); text-align: right; }
@keyframes fill {
0% { width: 0%; }
70%, 100% { width: 100%; }
} 反馈
Invalid input
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.shake-box {
animation-name: shake;
animation-duration: var(--anim-duration, 1.6s);
animation-timing-function: var(--anim-easing, ease-in-out);
padding: 14px 22px;
border-radius: 12px;
border: 1px solid #ef4444;
background: color-mix(in srgb, #ef4444 8%, #fff);
color: #dc2626;
font: 600 14px/1 'Plus Jakarta Sans', system-ui, sans-serif;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
15% { transform: translateX(-6px); }
30% { transform: translateX(6px); }
45% { transform: translateX(-5px); }
60% { transform: translateX(5px); }
75% { transform: translateX(-3px); }
} 成功对勾 查看详情 复制 Prompt 复制 CSS .anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.check { width: 72px; height: 72px; }
.check circle { fill: none; stroke: var(--anim-accent); stroke-width: 3; opacity: 0.25; }
.check path {
fill: none;
stroke: var(--anim-accent);
stroke-width: 4;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 60;
animation-name: draw;
animation-duration: var(--anim-duration, 1.8s);
animation-timing-function: var(--anim-easing, ease-in-out);
}
@keyframes draw {
0% { stroke-dashoffset: 60; }
70%, 100% { stroke-dashoffset: 0; }
} Saved
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.toast {
padding: 12px 18px;
border-radius: 10px;
background: var(--ink, #1a1c22);
color: #fff;
font: 600 13px/1 'Plus Jakarta Sans', system-ui, sans-serif;
box-shadow: 0 12px 30px -14px rgba(0, 0, 0, 0.5);
animation-name: toast;
animation-duration: var(--anim-duration, 3s);
animation-timing-function: var(--anim-easing, cubic-bezier(0.16, 1, 0.3, 1));
}
@keyframes toast {
0% { opacity: 0; transform: translateY(20px); }
15%, 75% { opacity: 1; transform: translateY(0); }
100% { opacity: 0; transform: translateY(20px); }
} 滚动触发
Revealed on scroll
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.scroll-demo { width: min(240px, 100%); height: 150px; border-radius: 12px; overflow: hidden; border: 1px solid var(--border, #e6e7ec); background: var(--surface, #fff); position: relative; }
.scroll-track { position: absolute; inset: 0; display: grid; place-items: center; }
.scroll-panel {
animation-name: reveal;
animation-duration: var(--anim-duration, 2.6s);
animation-timing-function: var(--anim-easing, cubic-bezier(0.16, 1, 0.3, 1));
width: 150px;
padding: 16px;
border-radius: 10px;
background: color-mix(in srgb, var(--anim-accent) 12%, #fff);
border: 1px solid color-mix(in srgb, var(--anim-accent) 30%, #e6e7ec);
color: var(--ink, #1a1c22);
font: 600 13px/1.4 'Plus Jakarta Sans', system-ui, sans-serif;
text-align: center;
}
@keyframes reveal {
0% { opacity: 0; transform: translateY(46px); }
30%, 100% { opacity: 1; transform: translateY(0); }
} .anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.parallax { width: min(240px, 100%); height: 150px; border-radius: 12px; overflow: hidden; position: relative; background: #0f1226; }
.parallax .par-layer { position: absolute; inset: -20px; }
.parallax .par-back {
background: radial-gradient(60% 60% at 30% 30%, color-mix(in srgb, var(--anim-accent) 70%, transparent), transparent 70%), radial-gradient(50% 50% at 75% 70%, #2a2f5e, transparent 70%);
animation-name: parBack;
animation-duration: var(--anim-duration, 3s);
animation-timing-function: var(--anim-easing, ease-in-out);
}
.parallax .par-front {
background: radial-gradient(40% 40% at 60% 40%, rgba(255, 255, 255, 0.35), transparent 70%);
animation-name: parFront;
animation-duration: var(--anim-duration, 3s);
animation-timing-function: var(--anim-easing, ease-in-out);
}
@keyframes parBack { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }
@keyframes parFront { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(12px); } } 注意力引导
脉冲 CTA 查看详情 复制 Prompt 复制 CSS 跑马灯 查看详情 复制 Prompt 复制 CSS 打字机 查看详情 复制 Prompt 复制 CSS 流光描边 查看详情 复制 Prompt 复制 CSS
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.pulse-cta-btn {
animation-name: pulse;
animation-duration: var(--anim-duration, 1.8s);
animation-timing-function: var(--anim-easing, ease-in-out);
border: 0;
border-radius: 12px;
padding: 14px 26px;
font: 600 15px/1 'Plus Jakarta Sans', system-ui, sans-serif;
color: #fff;
background: var(--anim-accent);
cursor: pointer;
}
@keyframes pulse {
0%, 100% { transform: scale(1); box-shadow: 0 8px 20px -8px color-mix(in srgb, var(--anim-accent) 45%, transparent); }
50% { transform: scale(1.05); box-shadow: 0 10px 34px -6px color-mix(in srgb, var(--anim-accent) 65%, transparent); }
} New · Sale · Live now ·
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.marquee {
overflow: hidden;
white-space: nowrap;
width: min(240px, 100%);
border-radius: 10px;
padding: 12px 0;
background: var(--surface, #fff);
border: 1px solid var(--border, #e6e7ec);
animation-name: marquee;
animation-duration: var(--anim-duration, 6s);
animation-timing-function: var(--anim-easing, linear);
}
.marquee span {
display: inline-block;
padding-left: 100%;
font: 600 14px/1 'IBM Plex Mono', monospace;
color: var(--ink, #1a1c22);
}
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-100%); }
} Typing…
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.type {
overflow: hidden;
white-space: nowrap;
font: 600 16px/1.3 'IBM Plex Mono', monospace;
color: var(--ink, #1a1c22);
animation-name: typing;
animation-duration: var(--anim-duration, 3.4s);
animation-timing-function: var(--anim-easing, steps(12, end));
}
.type .caret {
display: inline-block;
width: 2px;
height: 1.1em;
background: var(--anim-accent);
margin-left: 3px;
vertical-align: -0.15em;
}
.caret { animation: blink 1s steps(1) infinite; }
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
@keyframes typing {
0% { clip-path: inset(0 100% 0 0); }
55%, 100% { clip-path: inset(0 0 0 0); }
} Live
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.glow {
position: relative;
padding: 16px 22px;
border-radius: 14px;
background: var(--surface, #fff);
color: var(--ink, #1a1c22);
font: 600 14px/1 'Plus Jakarta Sans', system-ui, sans-serif;
isolation: isolate;
}
.glow::before {
content: '';
position: absolute;
inset: -2px;
border-radius: inherit;
background: conic-gradient(from 0deg, var(--anim-accent), transparent 35%, var(--anim-accent));
z-index: -1;
animation-name: spin;
animation-duration: var(--anim-duration, 4s);
animation-timing-function: var(--anim-easing, linear);
}
@keyframes spin {
to { transform: rotate(360deg); }
} 形变与变换
图标形变 查看详情 复制 Prompt 复制 CSS
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.morph { position: relative; width: 72px; height: 72px; }
.morph svg { position: absolute; inset: 0; width: 72px; height: 72px; }
.morph .morph-a {
animation-name: morphA;
animation-duration: var(--anim-duration, 2s);
animation-timing-function: var(--anim-easing, ease-in-out);
stroke: var(--anim-accent);
}
.morph .morph-b {
animation-name: morphB;
animation-duration: var(--anim-duration, 2s);
animation-timing-function: var(--anim-easing, ease-in-out);
stroke: var(--anim-accent);
}
@keyframes morphA {
0%, 45% { opacity: 1; transform: rotate(0) scale(1); }
55%, 100% { opacity: 0; transform: rotate(90deg) scale(0.6); }
}
@keyframes morphB {
0%, 45% { opacity: 0; transform: rotate(-90deg) scale(0.6); }
55%, 100% { opacity: 1; transform: rotate(0) scale(1); }
} Front
Back
.anim-el {
animation-iteration-count: infinite;
animation-fill-mode: both;
}
:root { --anim-accent: #6d5efc; }
.flip { perspective: 700px; width: min(150px, 100%); height: 100px; }
.flip-inner {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
animation-name: flip;
animation-duration: var(--anim-duration, 3.2s);
animation-timing-function: var(--anim-easing, cubic-bezier(0.4, 0, 0.2, 1));
}
.flip-front,
.flip-back {
position: absolute;
inset: 0;
display: grid;
place-items: center;
border-radius: 12px;
backface-visibility: hidden;
font: 600 14px/1 'Plus Jakarta Sans', system-ui, sans-serif;
}
.flip-front { background: var(--anim-accent); color: #fff; }
.flip-back {
background: var(--surface, #fff);
border: 1px solid var(--border, #e6e7ec);
color: var(--ink, #1a1c22);
transform: rotateY(180deg);
}
@keyframes flip {
0%, 40% { transform: rotateY(0); }
60%, 100% { transform: rotateY(180deg); }
} 暂无符合筛选的内容。