در درس 49، انیمیشن ها و @keyframes در CSS را با دو نمونه قابل کنترل یاد می گیریم: ورود کوتاه یک کارت و حرکت محدود یک نقطه تزئینی. کاربر خودش اجرا را شروع می کند، می تواند حرکت نقطه را موقتا متوقف کند و در حالت کاهش حرکت، محتوا بدون انیمیشن باقی می ماند. هدف، ساخت حرکت قابل فهم است؛ نه پنهان کردن متن یا جلب توجه دائمی.
دانلود پروژه درس 49 + پاسخ تمرین
صفحه آماده اجرا، فایل CSS، فونت محلی، راهنمای آزمایش و پاسخ جداگانه تمرین
دانلود فایل ZIP پروژه درس 49 و پاسخ تمرین
پس از استخراج، index.html را باز کنید؛ اینترنت لازم نیست.
تفاوت animation و transition
در درس انتقال ها با transition تغییر بین دو حالت، مثل رنگ معمولی و رنگ فوکوس، را نرم کردیم. در animation می توان مراحل یک حرکت را با نام مشخص تعریف کرد و مدت، تکرار و جهت اجرای آن را مستقل تنظیم کرد. شروع انیمیشن هم می تواند نتیجه تغییر یک حالت باشد؛ در پروژه این جلسه از گزینه های checkbox استفاده می کنیم تا اجرا با تصمیم کاربر آغاز شود.
تعریف keyframes به تنهایی چیزی را حرکت نمی دهد. باید آن نام در animation-name یک عنصر به کار برود و مدت مناسبی داشته باشد. اگر نام اشتباه باشد یا زمان صفر بماند، نتیجه دیداری مورد انتظار ظاهر نمی شود. نام گذاری روشن، مثل card-enter، در عیب یابی کمک می کند.
تعریف شروع و پایان ورود کارت
@keyframes card-enter {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
from همان شروع و to پایان است. کارت از موقعیتی 12px پایین تر و شفافیت صفر به موقعیت اصلی و شفافیت کامل می رسد. این جابه جایی، فضای چیدمان را به اندازه margin تغییر نمی دهد؛ عنصر در جریان صفحه جای خودش را دارد. با این حال transform می تواند باعث همپوشانی یا بریده شدن در والد دارای سرریز محدود شود، پس فاصله واقعی را جداگانه بررسی کنید.
حالت پایه کارت در فایل CSS قابل مشاهده است: opacity برابر یک و transform برابر none است. متن را در حالت پایه پنهان نکرده ایم. بنابراین اگر حرکت غیرفعال شود، محتوا باقی می ماند. همچنین تغییر opacity، عنصر را از ترتیب فوکوس یا ساختار دسترس پذیری حذف نمی کند؛ آن را راهی برای مخفی کردن کنترل های قابل فوکوس در نظر نگیرید.
اتصال حرکت به انتخاب کاربر
#reveal:checked ~ .notice {
animation: card-enter 600ms ease-out 1;
}
این قاعده وقتی گزینه reveal انتخاب شود، روی کارت notice بعد از آن و با همان والد اعمال می شود. ساختار HTML مهم است؛ اگر کارت را داخل والد دیگری ببرید، انتخابگر خواهر عمومی ممکن است دیگر آن را پیدا نکند. برای مرور رابطه انتخابگرها و عناصر، درس انتخابگرهای CSS را ببینید.
انیمیشن 600 میلی ثانیه طول می کشد، با ease-out اجرا می شود و یک بار تکرار دارد. پس از پایان، چون حالت پایه با نتیجه نهایی هماهنگ است، کارت به وضعیت نامناسبی نمی پرد. برای اجرای دوباره، گزینه را بردارید و دوباره انتخاب کنید. صرف باقی ماندن checkbox در حالت انتخاب شده، انیمیشن تمام شده را از نو آغاز نمی کند.
اجزای animation را جداگانه بشناسید
.example {
animation-name: card-enter;
animation-duration: 600ms;
animation-timing-function: ease-out;
animation-delay: 0ms;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: none;
animation-play-state: running;
}
این نمونه، شکل بلند تنظیم های حرکت ورود است. duration زمان یک چرخه و delay زمان انتظار پیش از شروع است. در شکل کوتاه، اولین مقدار زمانی مدت و دومین مقدار زمانی تاخیر است. بهتر است نام keyframes متمایز باشد تا با واژه های تنظیم، مثل linear یا reverse، اشتباه نشود. همچنین نوشتن دوباره shorthand می تواند تنظیم های قبلی مانند play-state را به مقدار پیش فرض برگرداند؛ ترتیب اعلان ها را کنترل کنید.
مراحل میانی و درصدها
@keyframes small-lift {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
این مثال مستقل، یک رفت و برگشت عمودی را نشان می دهد. در نیمی از مدت چرخه، عنصر به نقطه بالاتر می رسد و در پایان برمی گردد. درصدها نسبت پیشرفت چرخه را مشخص می کنند؛ با easing غیرخطی، سرعت حرکت در طول مسیر ثابت نیست. اگر یکی از نقاط شروع یا پایان برای یک ویژگی تعریف نشده باشد، مرورگر می تواند از مقدار زیربنایی آن ویژگی استفاده کند. برای آموزش و عیب یابی، در نمونه های اولیه هر دو کران را صریح بنویسید.

تکرار، جهت و توقف موقت
@keyframes dot-travel {
from { transform: translateX(0); }
to { transform: translateX(-80px); }
}
#run:checked ~ .track .dot {
animation: dot-travel 1s ease-in-out 4 alternate;
}
#pause:checked ~ .track .dot {
animation-play-state: paused;
}
نقطه پروژه در حالت عادی از سمت راست شروع می کند و با مقدار منفی translateX به چپ می رود. alternate جهت چرخه های بعدی را یک در میان برمی گرداند. چهار چرخه یک ثانیه ای، بدون توقف، مجموعا چهار ثانیه اجرای فعال دارند؛ دو رفت و دو برگشت. توقف موقت، زمان سپری شده در حرکت را نگه می دارد و پس از برداشتن گزینه توقف، حرکت از همان جا ادامه پیدا می کند.
paused با حذف animation فرق دارد. حذف انیمیشن معمولا اثر آن را برمی دارد؛ توقف، موقعیت فعلی را نگه می دارد. اگر گزینه اجرا پس از پایان همچنان فعال است، گزینه توقف حرکت تمام شده را دوباره راه نمی اندازد. برای شروع تازه، اجرا را بردارید و دوباره فعال کنید. در پروژه، قاعده توقف بعد از shorthand اجرا آمده تا بازنویسی ناخواسته نشود.
fill-mode چه کاری می کند؟
با none، پس از پایان اثر انیمیشن روی ویژگی ها باقی نمی ماند و مقدارهای عادی CSS دیده می شوند. forwards اثر آخرین مرحله موثر را بعد از پایان نگه می دارد؛ آخرین مرحله به جهت و تعداد چرخه ها هم بستگی دارد. backwards می تواند در زمان تاخیر، اثر اولین مرحله موثر را اعمال کند و both هر دو رفتار را دارد.
forwards داده یا کلاس HTML را تغییر نمی دهد و جای طراحی حالت پایه را نمی گیرد. اگر انیمیشن حذف شود، نباید محتوای ضروری ناپدید شود. نمونه ورود این درس عمدا به forwards نیاز ندارد؛ مقدار نهایی و حالت پایه هر دو کارت را قابل مشاهده نگه می دارند. برای تنظیم مقدارهای مشترک، می توانید از روش متغیرهای CSS برای نام گذاری مدت ها استفاده کنید.
کاهش حرکت و کنترل صفحه کلید
@media (prefers-reduced-motion: reduce) {
#reveal:checked ~ .notice,
#run:checked ~ .track .dot {
animation: none;
}
}
در حالت کاهش حرکت، هر دو انیمیشن حذف می شوند. کارت همچنان قابل مشاهده است و نقطه در حالت پایه باقی می ماند. checkbox و label واقعی استفاده کرده ایم؛ کاربر با Tab به گزینه می رسد و با Space آن را تغییر می دهد. کادر فوکوس مستقل از انیمیشن است. برای جزئیات، درس hover و focus-visible را مرور کنید.
نقطه صرفا تزئینی است و با aria-hidden از محتوای کمکی کنار گذاشته شده است. آن را نشانه بارگذاری یا موفقیت یک درخواست واقعی معرفی نکرده ایم. در محصول واقعی، وضعیت باید از منطق واقعی برنامه بیاید؛ گردش یک شکل به تنهایی ثابت نمی کند کاری در حال انجام است. حرکت دائمی و چشمک زدن هم بدون ضرورت اضافه نکنید.
کارایی و جلوگیری از تداخل حرکت ها
برای این نمونه از transform و opacity استفاده شده است. این انتخاب معمولا از تغییر پیوسته عرض و حاشیه مناسب تر است، اما روان بودن را باید روی دستگاه واقعی بررسی کرد. اگر hover هم transform را روی همان عنصر تغییر دهد، انیمیشن فعال می تواند نتیجه مورد انتظار را تحت تاثیر قرار دهد. برای ترکیب حرکت ها، یک لایه داخلی مستقل یا طراحی ساده تر را بررسی کنید.
در درس سایه و فیلتر دیدیم که جلوه های دیداری هم هزینه و قواعد پشته بندی دارند. انیمیت کردن همزمان سایه بزرگ، فیلتر و حرکت روی تعداد زیادی کارت لزوما انتخاب مناسبی نیست. ابتدا نمونه کوچک بسازید و ابزارهای عملکرد مرورگر را ببینید. برای اندازه ظرف نمونه هم می توانید از توابع min و calc استفاده کنید؛ برای مرزهای بصری، کادر و سایه CSS مکمل این درس است.
آزمایش پروژه و خطاهای رایج
- پس از استخراج ZIP، index.html را باز کنید. بدون انتخاب گزینه ها نباید حرکتی اجرا شود.
- ورود کارت را اجرا کنید. پس از پایان، متن باید کامل باقی بماند. گزینه را بردارید و دوباره فعال کنید.
- حرکت نقطه را آغاز و وسط مسیر متوقف کنید. با ادامه، حرکت باید از همان موقعیت پیگیری شود.
- کاهش حرکت را در ابزار توسعه شبیه سازی کنید. متن و گزینه ها باقی می مانند، اما حرکت اجرا نمی شود.
- عرض های 320 و 768 پیکسل، بزرگ نمایی 200 درصد و استفاده از Tab و Space را بررسی کنید. هیچ اطلاعاتی نباید صرفا در حین حرکت قابل خواندن باشد.
اگر چیزی حرکت نمی کند، نام keyframes، مدت، تطبیق انتخابگر و وضعیت کاهش حرکت را بررسی کنید. اگر کارت بعد از پایان محو شد، حالت پایه و fill-mode را ببینید. اگر حرکت با هاور می پرد، بررسی کنید چند قاعده روی transform همان عنصر اثر می گذارند.
تمرین: ورود کوتاه با پاسخ مستقل
برای practice-card یک keyframes تازه تعریف کنید: از opacity صفر و translateY برابر 8px به opacity یک و جابه جایی صفر برسد. حرکت فقط پس از انتخاب practice-run، طی 400ms، با ease-out و یک بار اجرا شود. در کاهش حرکت آن را حذف کنید. پاسخ داخل solution.css جداست و به صورت پیش فرض متصل نیست.
بعد از حل مستقل، تغییر آزمایشی را بردارید و خط زیر را پس از style.css در head اضافه کنید. گزینه تمرین را با صفحه کلید هم فعال کنید و پس از پایان، باقی ماندن متن را ببینید.
<link rel="stylesheet" href="solution.css">
پرسش های متداول
آیا برای CSS animation به جاوااسکریپت نیاز داریم؟
در این نمونه خیر. کنترل ها با وضعیت checkbox کار می کنند. برای اتصال حرکت به رویداد واقعی برنامه ممکن است اسکریپت لازم شود.
چرا زمان کل بیشتر از چهار ثانیه شد؟
اگر توقف موقت فعال شده باشد، مدت توقف به زمان دیواری اضافه می شود. چهار ثانیه، زمان اجرای فعال چهار چرخه است.
آیا infinite برای هر نشانگر مناسب است؟
خیر. ضرورت حرکت، امکان توقف، دسترس پذیری و ارتباط آن با وضعیت واقعی را بررسی کنید. نمونه این درس تکرار محدود دارد.
دانلود پروژه درس 49 + پاسخ تمرین
صفحه آماده اجرا، فایل CSS، فونت محلی، راهنمای آزمایش و پاسخ جداگانه تمرین
دانلود فایل ZIP پروژه درس 49 و پاسخ تمرین
پس از استخراج، index.html را باز کنید؛ اینترنت لازم نیست.


بدون دیدگاه