انیمیشن در CSS
ترنزیشن گفت از A به B چقدر طول بکشد. Transform گفت پیکسلها کجا بروند. انیمیشن یک خط زمانی مینویسد: نقطهٔ وضعیت آرام بزند، لودر بیوقفه بچرخد، کارتها یکییکی وارد شوند — با @keyframes برای گامها و animation برای اجرا.
انیمیشن یعنی چه؟
دو تکه دارد: یک مجموعهٔ نامدار از @keyframes که استایل را در درصدها (یا from / to) میچیند، و قانونی که همان نام را با مدت، تأخیر اختیاری، تعداد تکرار، جهت، تابع زمانبندی و fill-mode پخش میکند. مرورگر بین ایستگاههای کلیدی میانیابی میکند.
نام باید یکی باشد: animation-name: pulse فقط وقتی کار میکند که @keyframes pulse وجود داشته باشد. یکی را عوض کنید و دیگری را نه — هیچ حرکتی نمیبینید.
کنترلهای انیمیشن در یک نگاه
📊 اجزای اصلی انیمیشن
| قطعه | نقش |
|---|---|
@keyframes name { … } |
خط زمانی مقادیر در % / from / to |
animation-name |
کدام مجموعهٔ keyframe پخش شود |
animation-duration |
طول یک دور (s یا ms) |
animation-timing-function |
نرمی داخل دور (ease، linear، …) |
animation-delay |
صبر قبل از دور اول |
animation-iteration-count |
چند بار تکرار (عدد یا infinite) |
animation-direction |
normal، reverse، alternate، alternate-reverse |
animation-fill-mode |
استایل قبل/بعد (none، forwards، backwards، both) |
animation shorthand |
name → duration → timing → delay → iteration → direction → fill-mode (ترتیب رایج) |
همهٔ longhand را با هم لازم ندارید. از name + duration شروع کنید؛ برای لودر infinite بگذارید، برای برگشت نرم alternate، و وقتی فریم آخر باید بماند forwards.
اولین خط زمانی — پالس آرام
Opacity و transform برای حرکت سبک مناسباند. یک پالس نرم تمرین خوبی برای اولین @keyframes است.
@keyframes pulse {
0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.55;
transform: scale(0.92);
}
}
.status-dot {
display: inline-block;
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
background: #16a34a;
animation: pulse 1.4s ease-in-out infinite;
}
0% و 100% یکیاند تا حلقه تمیز بسته شود. infinite دور را ادامه میدهد — برای نقطهٔ کوچک وضعیت خوب است؛ اگر کل هیرو صفحه را انیمیت کنید، شلوغ میشود.
چرخش بیوقفه — اسپینر با linear
چرخش با linear و infinite مثل اسپینر پیوسته دیده میشود. حتماً مسیر prefers-reduced-motion بگذارید که بچرخد یا بایستد.
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.loader {
width: 2rem;
height: 2rem;
border: 3px solid #e5e7eb;
border-top-color: #2563eb;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
.loader {
animation: none;
border-top-color: #e5e7eb;
}
}
to همان 100% است. اگر فقط به پایان دور اهمیت میدهید، شروع پیشفرض 0% (بدون transform) کافی است.
تأخیر و stagger — یک keyframe، شروعهای مختلف
یک مجموعهٔ keyframe میتواند چند عنصر را جلو ببرد. با animation-delay فاصله بیندازید تا فهرست پشتسرهم حس شود — بدون سه انیمیشن جدا.
@keyframes fade-up {
from {
opacity: 0;
transform: translateY(0.75rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.reveal-list li {
opacity: 0;
animation: fade-up 0.45s ease forwards;
}
.reveal-list li:nth-child(1) { animation-delay: 0s; }
.reveal-list li:nth-child(2) { animation-delay: 0.08s; }
.reveal-list li:nth-child(3) { animation-delay: 0.16s; }
forwards استایل فریم آخر را بعد از تمام شدن نگه میدارد — وگرنه آیتمها ممکن است به opacity: 0 قانون پایه برگردند. اینجا animation-fill-mode واقعاً کار میکند.
fill-mode برای ورود یکباره
ورود معمولاً یکبار اجرا میشود. fill-mode مشخص میکند استایل قبل از تأخیر و بعد از فریم آخر چطور بماند.
@keyframes card-in {
from {
opacity: 0;
transform: translateY(1rem) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.card-enter {
animation: card-in 0.5s ease 0.1s both;
}
در این shorthand: نام card-in، مدت 0.5s، easing ease، تأخیر 0.1s، fill-mode both. both در زمان تأخیر فریم اول را میگذارد و بعد از پایان، فریم آخر را نگه میدارد.
جهت، توقف پخش، و کی انیمیت نکنیم
animation-direction: alternate دورهای فرد را جلو و زوج را برعکس میبرد — برای بالا و پایین نرم بدون دوبارهنویسی keyframe. animation-play-state: paused انیمیشن در حال اجرا را متوقف میکند (مثلاً مکث تزئینی روی هاور).
برای عوض شدن سادهٔ رنگ روی هاور همان transition کافی است. وقتی حلقه، داستان چندگامه، یا حرکتی میخواهید که به یک سوییچ حالت گره نخورده، سراغ انیمیشن بروید. داخل keyframe ترجیح با transform و opacity است؛ انیمیت کردن width، height یا top سنگینتر است و اغلب چیدمان را میلرزاند.
خودتان تمرین کنید
- پالسی با سه ایستگاه (
0%/50%/100%) فقط روی opacity بسازید؛ بعد یکscaleخیلی کوچک اضافه کنید. - اسپینر با
spin+linear+infinite؛ بعدeaseبگذارید و حس ناهماهنگ را ببینید. - سه نشان را با همان
fade-upو تأخیرهای0s،0.1s،0.2sstagger کنید — با و بدونforwardsمقایسه کنید. - روی یک پنل shorthand بنویسید:
animation: card-in 0.5s ease 0.15s both؛bothرا بردارید و برگشت ناگهانی را ببینید. - زیر
prefers-reduced-motion: reduceبرای حلقههای تزئینیanimation: none(یا یک محو کوتاه) بگذارید.
اشتباههای رایج
- انتظار دارید محو هاور «تا ابد» تکرار شود — آن کار انیمیشن است، نه یک transition تنها
- نام
animation-nameبا@keyframesیکی نیست — بیصدا هیچ اتفاقی نمیافتد infiniteروی ناحیهٔ بزرگ و پرهیاهو بدون مکث یا مسیر reduced-motion- انیمیت ویژگیهای چیدمان (
width،margin،top) وقتی transform/opacity کافی است - فراموش کردن
forwards/bothدر reveal یکباره که پایهٔ قانونopacity: 0دارد
جمعبندی
@keyframesخط زمانی را میسازد؛animation(یا longhandها) آن را پخش میکند- با iteration، direction، delay و fill-mode حلقه، برگشت، stagger و ماندن انتها را کنترل کنید
- transform و opacity را ترجیح دهید؛ حرکت تزئینی را با prefers-reduced-motion محترم بشمارید
- برای تغییر سادهٔ حالت transition؛ برای چندگام و تکرار انیمیشن
- بعدی در Effects & Motion: فیلترهای CSS
🧠 دانش خود را بیازمایید
دانش خود را بیازمایید
خود را با این آزمون تعاملی به چالش بکشید و ببینید موضوع را چقدر خوب درک کردهاید
📝 دستورالعملها
- هر سوال را با دقت بخوانید
- بهترین پاسخ را برای هر سوال انتخاب کنید
- میتوانید آزمون را هر چند بار که میخواهید تکرار کنید
- پیشرفت شما در بالا نمایش داده میشود