نوشتن کوتاه‌شده‌ی animation؛ همه‌چیز تو یه خط

تا اینجا هفت ویژگی جداگانه برای animation یاد گرفتیم: name، duration، delay، iteration-count، direction، fill-mode، play-state و timing-function. نوشتن همه‌ی این‌ها به‌صورت جدا، هم طولانی می‌شه و هم خوندنش سخت. خوشبختانه CSS یه shorthand داره که همه‌ی این‌ها رو تو یه خط جمع می‌کنه.

shorthand چیه و چه ترتیبی داره؟

ویژگی animation خودش شورت‌هند همه‌ی این ویژگی‌هاست:

.box {
  animation: slide-in 1s ease-in-out 0.5s infinite alternate both;
}

این معادل نوشتن این هفت خط جداست:

.box {
  animation-name: slide-in;
  animation-duration: 1s;
  animation-timing-function: ease-in-out;
  animation-delay: 0.5s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
  animation-fill-mode: both;
}

برخلاف خیلی از shorthand های دیگه‌ی CSS، اینجا ترتیب نوشتن مقادیر (به‌جز چند استثنا) زیاد اهمیت نداره، چون مرورگر نوع هر مقدار رو از روی خودش تشخیص می‌ده؛ یعنی می‌فهمه 1s باید duration یا delay باشه، infinite باید iteration-count باشه، و ease-in-out باید timing-function باشه.

تنها استثنا: ترتیب بین دو مقدار زمانی

وقتی هم duration و هم delay رو با هم می‌نویسید (که هر دو یه واحد زمانی مثل s یا ms دارن)، مرورگر نمی‌تونه تشخیص بده کدوم کدومه، پس یه قانون ثابت داره: اولین مقدار زمانی همیشه duration در نظر گرفته می‌شه، دومی delay:

.box {
  animation: fade-in 2s 0.5s;
  /* duration: 2s, delay: 0.5s */
}

اگه فقط یه مقدار زمانی بنویسید، اون همیشه duration حساب می‌شه، نه delay.

چه مقادیری رو می‌شه حذف کرد؟

فقط animation-name اجباریه (چون بدون اسم، مرورگر نمی‌دونه کدوم keyframe رو اجرا کنه). بقیه رو می‌شه حذف کرد و مقدار پیش‌فرض خودشون رو می‌گیرن:

.box {
  animation: pulse 3s infinite;
}

اینجا فقط name، duration و iteration-count نوشته شده؛ بقیه (delay، direction، fill-mode، timing-function، play-state) پیش‌فرض خودشون رو می‌گیرن.

نوشتن چند انیمیشن هم‌زمان با shorthand

دقیقاً مثل حالت جدا-جدا، می‌شه با کاما چند انیمیشن رو هم‌زمان تعریف کرد:

.box {
  animation:
    slide-in 0.6s ease-out,
    pulse 2s ease-in-out 0.6s infinite alternate;
}

اینجا اولین انیمیشن (slide-in) یه بار اجرا می‌شه و بعد از تمومش، انیمیشن دوم (pulse) که با 0.6s تأخیر شروع شده، بی‌نهایت ادامه پیدا می‌کنه.

Composition: وقتی چند source هم‌زمان می‌خوان یه ویژگی رو کنترل کنن

یه مفهوم مهم که کمتر بهش پرداخته می‌شه، composition هست. فرض کنید یه المنت دارید که هم یه @keyframes روش transform اعمال می‌کنه، هم شما جداگانه یه transform استاتیک روش نوشتید:

.box {
  transform: rotate(45deg);
  animation: shake 0.5s infinite;
}

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(10px); }
}

اینجا یه تناقض پیش میاد: کدوم transform برنده می‌شه؟ به‌طور پیش‌فرض، مقادیری که تو keyframe تعریف شدن، کاملاً جایگزین مقدار استاتیک می‌شن؛ یعنی rotate(45deg) در طول اجرای انیمیشن نادیده گرفته می‌شه و فقط translateX از keyframe اعمال می‌شه.

ویژگی animation-composition (نسبتاً جدید و پشتیبانی مرورگرهاش رو حتماً چک کنید) اجازه می‌ده این رفتار رو تغییر بدید:

مقداررفتار
replaceپیش‌فرض؛ مقدار keyframe جایگزین مقدار قبلی می‌شه
addمقدار keyframe به مقدار قبلی اضافه می‌شه (ترکیب می‌شه)
accumulateمشابه add، ولی برای بعضی مقادیر (مثل transform) نتیجه‌ی متفاوتی داره
نکته مهم: اگه چند انیمیشن هم‌زمان می‌خوان یه ویژگی مشترک (مثل transform) رو کنترل کنن، بدون تنظیم درست composition، معمولاً فقط آخرین انیمیشنی که تعریف شده برنده می‌شه و بقیه بی‌اثر می‌مونن.

اشتباه رایج: فراموش کردن این‌که shorthand، مقادیر حذف‌شده رو ریست می‌کنه

اگه یه‌جا با شورت‌هند مقدار fill-mode رو ست کرده باشید و بعد یه‌جای دیگه دوباره shorthand بنویسید بدون این‌که fill-mode رو تکرار کنید، مقدار قبلی از بین می‌ره و به پیش‌فرض برمی‌گرده؛ چون هر بار که shorthand استفاده می‌شه، تمام هفت ویژگی زیرمجموعه‌اش ریست می‌شن، نه فقط اونی که نوشتید.

جمع‌بندی

shorthand ویژگی animation اجازه می‌ده همه‌ی هفت ویژگی جداگانه رو تو یه خط بنویسید؛ فقط اسم انیمیشن اجباریه و بقیه اختیاری‌ان. تنها نکته‌ی حساس، ترتیب دو مقدار زمانی (duration قبل از delay) هست. برای موقعیت‌های پیچیده‌تر که چند source هم‌زمان می‌خوان یه ویژگی رو کنترل کنن، animation-composition این امکان رو می‌ده که به‌جای جایگزینی کامل، مقادیر با هم ترکیب بشن.