IlmHamroh
JavaScript Full-stack/6-qism. CSS: harakat, zamonaviy CSS va dizayn4/57-dars22 daqiqa
Mundarija (36)

CSS animatsiya: @keyframes va animation xususiyatlari

Qisqacha: @keyframes animatsiyaning "ssenariysi": qaysi foizda element qanday ko'rinishda bo'lishi yoziladi (from, 50%, to). animation xususiyati bu ssenariyni elementga ulaydi: animation: muhr 0.4s ease-out. Transition'dan farqi — animatsiya hover kutmaydi, o'zi boshlanadi, ko'p bosqichli bo'ladi va takrorlanadi. fill-mode, direction, iteration-count va play-state uning xulqini boshqaradi.

Bu darsda

  • @keyframes qoidasini from/to va foizlar bilan yozasiz.
  • animation ning hamma xususiyatlarini — davomiylik, takror, yo'nalish, fill-mode, play-state — ishlatasiz va qisqa yozuvini o'qiysiz.
  • Bir nechta animatsiyani birlashtirasiz va animation-composition bilan ularni qo'shasiz.
  • Elementni offset-path bilan chiziq bo'ylab yurgizasiz.
  • Animatsiyaning kaskaddagi o'rnini, animationend hodisasini va xavfsiz harakat qoidalarini bilasiz.

Oldin bilishingiz kerak: Transition va timing funksiyalari, 2D transformlar, CSS o'zgaruvchilari 1, Foydalanuvchi afzalliklari.

1. Nega bu kerak?

O'tgan darsda transition'ni o'rgandik. U ajoyib, lekin uchta cheklovi bor:

  1. Turtki kerak. Transition faqat qiymat o'zgarganda ishlaydi — hover, fokus, class. Sahifa ochilganda o'zi boshlanmaydi.
  2. Faqat ikki nuqta. A dan B ga. "Avval kattalash, keyin kichray, keyin joyiga qayt" — yo'q.
  3. Takrorlanmaydi. Bir marta o'tadi va tugaydi.

Choynakdan chiqayotgan bug'ni tasavvur qiling: u o'zi ko'tariladi, yo'lda kengayadi va eriydi, keyin yana. Bunga hech kim "turtki" bermaydi. Yuklanish belgisi ham shunday — to'xtovsiz aylanadi. Bunday harakatlar uchun animatsiya kerak.

Ikki qism bor: @keyframes — harakat ssenariysi, va animation — ssenariyni elementga ulash. Xuddi choyxonadagi oshpaz Rustam akaning retsepti va uni pishirish buyrug'i kabi: retsept bir marta yoziladi, uni istalgan qozonda pishirish mumkin.

2. @keyframes: ssenariy

2.1 Birinchi animatsiya

css
@keyframes bug {
  from {
    opacity: 0.8;
    translate: 0 0;
  }
  to {
    opacity: 0;
    translate: 0 -2rem;
  }
}

.bug {
  animation: bug 2s ease-out;
}
  • @keyframes bug — ssenariy va uning nomi (bug). Nomni o'zingiz tanlaysiz, qo'shtirnoqsiz.
  • from — boshlanish holati, to — tugash holati.
  • animation: bug 2s ease-out — ".bug elementida bug ssenariysini 2 soniyada, ease-out bilan o'ynat".

@keyframes — CSS nima darsida tilga olingan @-qoidalardan biri. U hech qanday elementni o'zi tanlamaydi — faqat ssenariyni saqlaydi.

2.2 Foizlar: ko'p bosqich

from — bu 0%, to — 100%. Orasiga istalgancha bosqich qo'shish mumkin:

css
@keyframes muhr {
  0% {
    opacity: 0;
    scale: 2;
  }
  60% {
    opacity: 1;
    scale: 0.9;
  }
  100% {
    scale: 1;
  }
}

"Boshida ko'rinmas va ikki barobar katta; vaqtning 60 foizida ko'rindi va biroz kichrayib ketdi; oxirida asl o'lchamga qaytdi" — xuddi qog'ozga zarb bilan bosilgan muhr.

Uchta foydali qoida:

  • Bir xil bosqichlarni birlashtirish mumkin: 0%, 100% { opacity: 1; } — boshi va oxiri bir xil.
  • Yozilmagan xususiyat elementning o'z qiymatidan olinadi. 100% da opacity yo'q — brauzer elementning oddiy opacity sini (1) oladi. from ni butunlay tushirib qoldirsa ham bo'ladi: animatsiya elementning hozirgi holatidan boshlanadi.
  • !important ssenariy ichida ishlamaydi. Chrome'da tekshirdik: @keyframes ichida color: green !important yozdik — shu deklaratsiya butunlay tashlandi, qo'shni background-color esa ishladi.

Tekshirib ko'ring: @keyframes silkinish { 25% { translate: -4px; } 75% { translate: 4px; } } — 0% va 100% da element qayerda?

Javob

O'z joyida — elementning oddiy translate qiymatida (odatda none, ya'ni 0). 0% va 100% yozilmagan, brauzer ularni elementning o'z qiymatidan to'ldiradi. Natijada element joyidan chapga, keyin o'ngga borib, yana joyiga qaytadi — silkinadi.

3. animation xususiyatlari

3.1 To'liq ro'yxat

Xususiyat Nima Odatiy qiymat
animation-name Qaysi @keyframes none
animation-duration Bir aylanish qancha 0s
animation-timing-function Tezlik egri chizig'i ease
animation-delay Qancha kutib boshlansin 0s
animation-iteration-count Necha marta 1
animation-direction Qaysi yo'nalishda normal
animation-fill-mode Oldin va keyin nima bo'lsin none
animation-play-state O'ynayaptimi, pauzadami running

animation-duration ning odatiy qiymati — 0s. Ya'ni vaqtni yozishni unutsangiz, animatsiya bir zumda "o'ynab" tugaydi va hech narsa ko'rinmaydi.

3.2 Qisqa yozuv

css
.bug {
  animation: bug 2s ease-out 0.5s 3 normal both;
  /*   nom davomiylik timing kechikish takror yo'nalish fill */
}

Transition'dagi kabi: birinchi vaqt — davomiylik, ikkinchisi — kechikish. Qolganini brauzer ko'rinishidan taniydi.

Bitta tuzoq: nom kalit so'zga o'xshamasin. @keyframes ease { ... } va animation: ease 1s — brauzer ease ni timing funksiyasi deb o'qiydi va animatsiya nomi none bo'lib qoladi. infinite, alternate, forwards va boshqa kalit so'zlar ham shunday. O'zbekcha nomlar (bug, muhr, ochilish) bu xavfdan xoli.

3.3 Takror: animation-iteration-count

  • Son: 1, 3. Kasr ham bo'ladi: 0.5 — yarmida to'xtaydi.
  • infinite — to'xtovsiz.

3.4 Yo'nalish: animation-direction

Qiymat Ma'nosi
normal Har safar from → to
reverse Har safar to → from
alternate Toq aylanishda oldinga, juftda orqaga
alternate-reverse Aksincha: avval orqaga

alternate "borib-kelish" uchun: 0 dan 100 ga, keyin 100 dan 0 ga — sakrashsiz. Chrome'da 1 soniyali, 3 marta alternate animatsiyani o'lchadik: 1.25 soniyada (ikkinchi aylanishning choragi) element 75 pikselda edi — orqaga qaytayotgan edi. 2.25 soniyada (uchinchi aylanish) — 25 pikselda, yana oldinga.

3.5 animation-fill-mode: oldin va keyin

Bu — eng ko'p chalkashtiradigan xususiyat. Savol: animatsiya boshlanmasdan oldin (kechikish paytida) va tugagandan keyin element qanday ko'rinishda bo'ladi?

Chrome'da o'lchadik. Elementning o'z qiymati translate: 20px, animatsiya 0 dan 100 pikselga, 1 soniya kutib, 1 soniya davom etadi:

fill-mode Kutish paytida O'rtasida Tugagach
none (odatiy) 20 px (o'z qiymati) 50 px 20 px — orqaga sakradi
forwards 20 px 50 px 100 px — oxirida qoldi
backwards 0 px — boshida turdi 50 px 20 px
both 0 px 50 px 100 px

Odatiy none bilan element animatsiyadan keyin "sakrab" asl holatiga qaytadi. Shuning uchun paydo bo'lish animatsiyalarida ko'pincha both yoziladi: kutish paytida element boshlang'ich holatda (masalan, ko'rinmas) turadi, tugagach — oxirgi holatda qoladi.

Diqqat: forwards bilan qolgan qiymat element qoidasidagidan kuchli — animatsiya "o'lik" bo'lsa ham qiymatni ushlab turadi. Keyin hover'da o'sha xususiyatni o'zgartirsangiz, ishlamaydi. Iloji bo'lsa, elementning oddiy qiymatini oxirgi holat qilib yozing va fill-mode ni faqat backwards qiling. display darsidagi tuzoqni ham eslang: opacity: 0 bilan "qolib ketgan" element bosiladi va fokus oladi.

3.6 animation-play-state: pauza

paused animatsiyani joyida to'xtatadi, running davom ettiradi. Masalan, sichqoncha kelganda aylanib turgan belgi to'xtasin:

css
.bug:hover {
  animation-play-state: paused;
}

Tekshirib ko'ring: Xabar pastdan suzib chiqishi kerak: @keyframes chiqish { from { translate: 0 1rem; opacity: 0; } }, animation: chiqish 0.3s ease-out 1s. Sahifa ochilgach birinchi soniyada foydalanuvchi nimani ko'radi va buni qanday tuzatasiz?

Javob

Xabarni o'z joyida, to'liq ko'rinib turganini ko'radi. 1 soniya o'tgach u birdan yo'qoladi va pastdan suzib chiqadi — "miltillash". Sababi — odatiy fill-mode: none: kechikish paytida from qo'llanmaydi. Tuzatish: backwards (yoki both) qo'shing — animation: chiqish 0.3s ease-out 1s backwards.

4. «Bahor» choynagi: bug' ko'tariladi

Endi hammasini birga ishlatamiz. Choynak ustida uchta bug' chizig'i ko'tarilib eriydi. Har biri biroz kechikib boshlanadi — tabiiyroq:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-ikkinchi: #5b6660;
    --rang-fon: #fffaf0;
  }
  body {
    font-family: system-ui, sans-serif;
    background-color: var(--rang-fon);
  }
  .choynak {
    position: relative;
    width: 8rem;
    margin: 4rem auto 1rem;
    font-size: 4rem;
    text-align: center;
  }
  .bug {
    position: absolute;
    bottom: 100%;
    width: 0.4rem;
    height: 2.5rem;
    border-radius: 1rem;
    background: linear-gradient(
      transparent, var(--rang-ikkinchi)
    );
    opacity: 0.5;
  }
  .bug:nth-child(1) { left: 2.5rem; --i: 0; }
  .bug:nth-child(2) { left: 3.8rem; --i: 1; }
  .bug:nth-child(3) { left: 5.1rem; --i: 2; }
  @keyframes bug {
    from {
      opacity: 0.6;
      translate: 0 0.5rem;
      scale: 1 0.6;
    }
    to {
      opacity: 0;
      translate: 0 -1.5rem;
      scale: 1.8 1.2;
    }
  }
  @media (prefers-reduced-motion: no-preference) {
    .bug {
      animation: bug 2s ease-out calc(var(--i) * 0.4s) 2 backwards;
    }
  }
  p { text-align: center; color: var(--rang-asosiy); }
</style>
<div class="choynak" aria-hidden="true">
  <span class="bug"></span>
  <span class="bug"></span>
  <span class="bug"></span>
  🫖
</div>
<p>Ko'k choy — 5 000 so'm</p>

Nimaga qarang: choynak ustidagi uchta kulrang chiziq navbat bilan — 0.4 soniya oraliq bilan — ko'tarilib, kengayib, eriydi. Har biri ikki marta, keyin to'xtaydi. Skrinshot animatsiyaning bitta kadrini ko'rsatadi; natijani qayta ochsangiz, harakat qaytadan boshlanadi.

Kodda uchta qaror:

  • Kechikish o'zgaruvchidan. --i har chiziqda boshqacha: 0, 1, 2. calc(var(--i) * 0.4s) — 0, 0.4 va 0.8 soniya (CSS o'zgaruvchilari 1, Matematik funksiyalar). Bitta animation qatori uchta har xil kechikish berdi. Bu naqsh "ketma-ket paydo bo'lish" (stagger) deyiladi — ro'yxat elementlarini birma-bir chiqarishda ham ishlatiladi (Micro-interaktsiyalar).
  • backwards — kechikish paytida chiziq from holatida turadi. Usiz ikkinchi va uchinchi chiziq kutish paytida .bug qoidasidagi opacity: 0.5 bilan "osilib" turardi.
  • Ikki marta, infinite emas. Bu bezak. To'xtovsiz harakatlanadigan narsa matnni o'qishga xalaqit beradi. WCAG'ning 2.2.2 mezoni (A daraja): 5 soniyadan uzoq davom etadigan avtomatik harakatni foydalanuvchi to'xtata olishi kerak. Bizda 2 × 2 soniya + 0.8 kechikish = 4.8 soniya — chegaradan past. To'xtovsiz bug' esa to'xtatish tugmasisiz — aniq xato. Harakat qoidalarini Harakat etikasi darsida chuqur ko'ramiz.

Choynakka aria-hidden="true" berildi: bu bezak, ekran o'quvchi uni "choynak emojisi" deb o'qimasin (SVG va ikonkalar darsidagi qoida).

5. Menyu tepadan "tushib" ochiladi

2D transformlar darsida transform-origin haqida "menyu ochilganda tepadan pastga tushib chiqishi uchun transform-origin: top va scaleY birga ishlatiladi" degan edik. Mana u.

«Bahor» menyu sahifasidagi "Ichimliklar" bo'limi details bilan yozilgan (details va summary). Ochilganda ro'yxat tepadan pastga yoyilsin:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  details {
    max-width: 18rem;
    border: 2px solid var(--rang-asosiy);
    border-radius: 0.5rem;
    background-color: var(--rang-fon);
  }
  summary {
    padding: 0.5rem 0.75rem;
    color: var(--rang-asosiy);
    font-weight: bold;
  }
  ul { margin: 0; padding: 0 0.75rem 0.75rem 2rem; }
  @keyframes ochilish {
    from {
      opacity: 0;
      scale: 1 0;
    }
  }
  @media (prefers-reduced-motion: no-preference) {
    details[open] > ul {
      transform-origin: top;
      animation: ochilish 0.2s ease-out;
    }
  }
</style>
<details>
  <summary>Ichimliklar</summary>
  <ul>
    <li>Ko'k choy — 5 000 so'm</li>
    <li>Qora choy — 5 000 so'm</li>
    <li>Kompot — 8 000 so'm</li>
  </ul>
</details>

Nimaga qarang: "Ichimliklar" ni bosing — ro'yxat yuqori chetidan pastga "tushib" ochiladi va xiralikdan chiqadi. Yopib qayta ochsangiz — yana. Harakatni kamaytirgan foydalanuvchida ro'yxat darhol ochiladi.

Uch nozik joy:

  • Faqat from. to yozilmagan — oxirgi holat elementning o'z qiymati (opacity: 1, scale: 1). «Foizlar: ko'p bosqich» bo'limidagi qoida ishladi: yozilmagani elementdan olinadi. Bu fill-mode siz ham "sakrash" bermaydi.
  • Nega transition emas? Yopiq details ning ichi chizilmaydi — ro'yxatning "oldingi" holati yo'q, transition'ga "qayerdan" boshlashni aytib bo'lmaydi. Animatsiya esa element chizila boshlagan zahoti o'zi ishga tushadi. Chrome'da tekshirdik: details ni yopib qayta ochganimizda animatsiya har safar noldan boshlandi.
  • Yopilishda animatsiya yo'q — details darhol yopiladi. Yopilishni ham silliq qilishning yangi yo'llarini keyingi darsda ko'ramiz.

Maslahat: scale: 1 0 elementni faqat ko'rinishda siqadi — uning joyi darhol to'liq bo'ladi, ostidagi matn sakrab pastga tushadi. Balandlikning o'zini silliq o'zgartirish ham keyingi darsda.

6. Bir nechta animatsiya

6.1 Vergul bilan ro'yxat

Bitta elementga bir necha animatsiya berish mumkin — transition'dagi kabi vergul bilan:

css
.yangi::before {
  animation:
    muhr 0.4s ease-out both,
    silkinish 0.3s ease-in-out 0.4s 2;
}

Avval muhr bosiladi, 0.4 soniyadan keyin ikki marta silkinadi. Ikkala animatsiya bir xususiyatni o'zgartirsa, ro'yxatdagi keyingisi yutadi.

6.2 animation-composition: qo'shish

Kartada transform: translateX(50px) bor. Unga transform: translateY(20px) ni o'zgartiradigan animatsiya berdik. Chrome'da o'lchadik: animatsiya o'rtasida transform — matrix(1, 0, 0, 1, 0, 10). X bo'yicha 50 piksel yo'qoldi: animatsiya elementning transform ini to'liq almashtirdi.

animation-composition bu xulqni o'zgartiradi:

Qiymat Ma'nosi
replace (odatiy) Animatsiya qiymati elementnikini almashtiradi
add Qo'shiladi: element translateX(50px) + animatsiya translateY(...)
accumulate Sonlar yig'iladi: translateX(50px) + translateX(10px) = translateX(60px)

animation-composition: add bilan o'sha o'lchov matrix(1, 0, 0, 1, 50, 10) berdi — X ham, Y ham joyida.

Baseline ma'lumotiga ko'ra animation-composition 2023-yil iyuldan hamma asosiy brauzerda, 2026-yil yanvardan keng tarqalgan Baseline.

Lekin eng oddiy yechim — 2D transformlar darsidagi alohida xususiyatlar. Element rotate: -12deg bilan burilgan, animatsiya faqat scale ni o'zgartirsa — ular to'qnashmaydi, animation-composition shart emas. Muhr misolida aynan shunday qildik.

7. offset-path: chiziq bo'ylab harakat

translate elementni to'g'ri chiziq bo'ylab suradi. Egri yo'l kerak bo'lsa — offset-path: elementga "shu yo'ldan yur" deydi. Yo'l SVG'dagi kabi path() bilan yoziladi (SVG), elementning yo'ldagi joyi esa offset-distance bilan: 0% — boshi, 100% — oxiri. Animatsiya offset-distance ni o'zgartiradi.

«Bahor» yetkazib berish sahifasi uchun: taksi choyxonadan uyga egri yo'l bilan boradi.

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-ikkinchi: #5b6660;
    --rang-urgu: #b4461a;
  }
  body { font-family: system-ui, sans-serif; }
  .xarita {
    position: relative;
    width: 300px;
    height: 140px;
    margin: 1rem auto;
  }
  .xarita svg {
    position: absolute;
    inset: 0;
  }
  .yol {
    fill: none;
    stroke: var(--rang-ikkinchi);
    stroke-width: 2;
    stroke-dasharray: 6 6;
  }
  .taksi {
    position: absolute;
    top: 0;
    left: 0;
    font-size: 1.5rem;
    line-height: 1;
    offset-path: path("M20 110 C90 110 90 30 160 30 S250 110 280 40");
    offset-distance: 60%;
    offset-rotate: 0deg;
  }
  @keyframes yetkazish {
    from { offset-distance: 0%; }
    to { offset-distance: 100%; }
  }
  @media (prefers-reduced-motion: no-preference) {
    .taksi {
      animation: yetkazish 4s ease-in-out 2 alternate both;
    }
  }
  .belgi {
    position: absolute;
    font-size: 0.8rem;
    color: var(--rang-asosiy);
    font-weight: bold;
  }
  .b1 { left: 0; top: 118px; }
  .b2 { right: 0; top: 10px; color: var(--rang-urgu); }
</style>
<div class="xarita">
  <svg viewBox="0 0 300 140" aria-hidden="true">
    <path class="yol"
      d="M20 110 C90 110 90 30 160 30 S250 110 280 40"/>
  </svg>
  <span class="taksi" aria-hidden="true">🚕</span>
  <span class="belgi b1">«Bahor»</span>
  <span class="belgi b2">Uyingiz</span>
</div>

Nimaga qarang: punktir yo'l — SVG'da chizilgan, taksi — oddiy span, lekin u aynan o'sha yo'l bo'ylab yuradi: offset-path dagi yo'l SVG'dagi d bilan bir xil. 4 soniyada "Uyingiz" ga yetib, alternate bilan qaytadi. Harakat kamaytirilgan bo'lsa, taksi yo'lning 60 foizida — offset-distance: 60% da — to'xtab turadi: bu elementning oddiy qiymati, animatsiyasiz ham ma'noli holat.

  • offset-rotate: 0deg — taksi yo'l burilishlariga qarab aylanmasin. Odatiy auto da element yo'l yo'nalishiga buriladi — samolyot yoki strelka uchun qulay, emoji uchun esa g'alati.
  • Yo'l koordinatalari — elementning containing block'iga nisbatan (position). Shuning uchun .xarita — position: relative, taksi — top: 0; left: 0.

Baseline ma'lumotiga ko'ra "Motion path" (offset-path, offset-distance, offset-rotate) 2022-yil sentabrdan hamma asosiy brauzerda, 2025-yil martdan keng tarqalgan Baseline.

8. Animatsiya va kaskad

Kaskad darsida va'da qilgan edik. O'tgan darsda transition kaskadning eng kuchli manbai ekanini ko'rdik. Animatsiyaning joyi boshqa: u oddiy muallif qoidalaridan kuchli, lekin !important dan kuchsiz.

Chrome'da tekshirdik:

  • Paragrafda color: red, animatsiya esa rangni ko'k qiladi. Animatsiya paytida rang — ko'k: animatsiya oddiy qoidani yengdi.
  • Paragrafda color: red !important va xuddi shu animatsiya. Rang — qizil: !important animatsiyani yengdi.

Kuchlar tartibini to'liq yozamiz — eng kuchlisi tepada:

Kuch Nima
1 Transition
2 !important (brauzer → foydalanuvchi → muallif)
3 Animatsiya
4 Oddiy qoidalar (muallif → foydalanuvchi → brauzer)

Nega shunday? Animatsiya — dizaynerning vaqtinchalik niyati, u oddiy qoidalarni bosib o'tishi kerak — aks holda hech qanday animatsiya ishlamas edi. Lekin !important, ayniqsa foydalanuvchiniki, — himoya: ko'rish qobiliyati past odam o'rnatgan rangni sayt animatsiyasi "tortib olmasligi" kerak.

9. JavaScript bilan bog'lanish

JavaScript tilini 08-qismda, sahifa elementlari va hodisalar bilan ishlashni 09-qismda o'rganasiz — hozir faqat nima borligini biling.

Hodisalar. Transition'dagi kabi, animatsiya ham xabar beradi:

js
const muhr = document.querySelector(".yangi");

muhr.addEventListener("animationend", (hodisa) => {
  console.log(hodisa.animationName, "tugadi");
});

animationstart — boshlanganda, animationiteration — har yangi aylanishda, animationend — tugaganda. infinite animatsiyada animationend hech qachon kelmaydi.

Web Animations API. Brauzer har CSS animatsiyasini JavaScript'ga ham ko'rsatadi — skript uni ushlab, to'xtatib yoki surib qo'ya oladi. Masalan, document.getAnimations() sahifadagi hamma animatsiyalar ro'yxatini beradi — biz bu darsdagi hamma o'lchovlarni aynan shu yo'l bilan qildik: animatsiyani to'xtatib, kerakli soniyaga surib, qiymatni o'qidik.

js
for (const animatsiya of document.getAnimations()) {
  animatsiya.pause();
}

Bu kod sahifadagi hamma CSS animatsiyalar va transition'larni to'xtatadi. JavaScript'da animatsiyani noldan yaratish ham mumkin — element.animate(); u @keyframes bilan bir xil tushunchalarda ishlaydi.

DevTools'da esa Animations paneli bor: sahifadagi animatsiyalarni yozib oladi, sekinlashtirib ko'rsatadi va vaqt chizig'ida ko'rsatadi.

10. «Bahor»: muhr bosiladi

2D transformlar darsidagi "Yangi" muhri endi sahifa ochilganda "bosiladi": katta va ko'rinmas holatdan zarb bilan tushadi.

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
  }
  body {
    padding: 1.5rem;
    font-family: system-ui, sans-serif;
  }
  .taom-karta {
    position: relative;
    max-width: 16rem;
    padding: 0.75rem 1rem;
    border: 2px solid var(--rang-asosiy);
    border-radius: 0.5rem;
    background-color: var(--rang-fon);
  }
  .taom-nomi { margin: 0; color: var(--rang-asosiy); }
  .narx { color: var(--rang-urgu); font-weight: bold; }
  .yangi::before {
    content: "Yangi";
    position: absolute;
    top: 0;
    right: 0;
    padding: 0.25rem 0.5rem;
    border: 2px solid var(--rang-urgu);
    border-radius: 0.25rem;
    background-color: var(--rang-fon);
    color: var(--rang-urgu);
    font-weight: bold;
    translate: 30% -50%;
    rotate: -12deg;
  }
  @keyframes muhr {
    0% {
      opacity: 0;
      scale: 2;
    }
    60% {
      opacity: 1;
      scale: 0.9;
    }
    100% {
      scale: 1;
    }
  }
  @media (prefers-reduced-motion: no-preference) {
    .yangi::before {
      animation: muhr 0.4s ease-in 0.3s backwards;
    }
  }
</style>
<article class="taom-karta yangi">
  <h3 class="taom-nomi">Manti</h3>
  <p>Narxi: <span class="narx">30 000 so'm</span></p>
</article>

Nimaga qarang: sahifa ochilgach 0.3 soniyadan keyin muhr ikki barobar katta va shaffof holatdan tushadi, biroz "cho'kadi" 0.9-bob va joyiga o'rnashadi. Qiyshayishi (rotate: -12deg) animatsiya davomida saqlanadi: animatsiya faqat scale va opacity ni o'zgartiradi, rotate esa alohida xususiyat.

  • ease-in — tushish tezlashib boradi, "zarb" bilan tugaydi. Qo'l bilan urib bosilgan muhrga o'xshaydi. Paydo bo'lishda odatda ease-out tavsiya qilamiz (Transition), lekin bu yerda ataylab "urilish" kerak.
  • backwards — 0.3 soniyalik kutishda muhr ko'rinmaydi. Usiz u avval joyida ko'rinib, keyin yo'qolib, qayta tushardi.
  • Harakat kamaytirilganda — muhr shunchaki joyida turadi.

11. Ko'p uchraydigan xatolar

11.1 Nom xato yozilgan

@keyframes ochilish va animation: ochlish 0.2s — hech narsa bo'lmaydi, xato xabari ham yo'q. Tuzatish: nomni nusxalab qo'ying. DevTools Styles'da animation-name ustiga kursor olib borsangiz, @keyframes qoidasi topilmasa buni ko'rasiz.

11.2 duration unutilgan

animation: bug ease-out — davomiylik 0s, animatsiya ko'rinmaydi. Tuzatish: vaqtni yozing.

11.3 Animatsiyadan keyin sakrash

Element oxirgi holatga yetib, birdan boshlang'ich holatiga qaytadi. Tuzatish: elementning oddiy qiymatini oxirgi holat qiling (to ni tushirib qoldiring) yoki fill-mode ni to'g'ri tanlang.

11.4 Animatsiyani "qayta ishga tushirib" bo'lmaydi

Bir marta tugagan animatsiya o'sha qoida turgan ekan, qayta boshlanmaydi. Qayta boshlash uchun animation-name o'zgarishi kerak: class olib tashlanib, qayta qo'shiladi (JavaScript bilan) yoki element display: none dan chiqadi. "Menyu tushib ochiladi" bo'limidagi details misoli aynan shu sabab bilan har ochilishda qayta ishladi.

11.5 Cheksiz va miltillovchi harakat

infinite bezak, sekundiga bir necha marta yonib-o'chadigan animatsiya. Tuzatish: bezak — 1–3 marta; miltillash — sekundiga 3 martadan ko'p hech qachon (WCAG 2.3.1: tutqanoq xavfi); hammasi — prefers-reduced-motion: no-preference ichida.

11.6 Layout xususiyatini animatsiya qilish

width, height, top, margin ni animatsiya qilish har kadrda layoutni qayta hisoblatadi — telefonda harakat "tutilib" qoladi. Tuzatish: imkon qadar translate, scale, opacity (Rendering va samaradorlik).

12. Mashqlar

1-mashq (oson): Diqqat tortuvchi belgi

«Bahor»ning .aksiya matni sahifa ochilganda uch marta "yurak urishi"dek kattalashib-kichraysin: 1 → 1.1 → 1. Bir urish — 0.6 soniya. Harakat faqat ruxsat bo'lsa.

Ishora: aksiya odatda p — blok element, scale unga ishlaydi. Boshi va oxiri bir xil bo'lsa, ularni birlashtirish yoki umuman yozmaslik mumkin.

Yechim
css
@keyframes urish {
  50% {
    scale: 1.1;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .aksiya {
    animation: urish 0.6s ease-in-out 3;
  }
}

Faqat 50% yozildi: 0% va 100% elementning o'z qiymati — scale: 1. ease-in-out — urish ikki tomonga ham yumshoq. 3 × 0.6 = 1.8 soniya — WCAG'ning 5 soniyalik chegarasidan ancha kam. Matn to'liq kengligida bo'lsa, scale uni o'rtadan kattalashtiradi — chetlari biroz tashqariga chiqadi, lekin qo'shnilar surilmaydi.

2-mashq (o'rta): Yozuv mashinkasi

«Bahor» bosh sahifasida shior harfma-harf "yozilsin": Choyxona «Bahor» — xush kelibsiz! (33 belgi). Oxirida kursor miltillab tursin.

Ishora: ch — bitta belgi eni (O'lcham birliklari). Matnni width: 0 dan 33ch gacha oching, overflow: hidden va white-space: nowrap bilan. Harf "sakrab" chiqishi uchun — steps(33) (Transition darsidagi zinapoya). ch aniq ishlashi uchun eni bir xil shrift kerak — monospace. Kursor — o'ng chegara, uning rangi steps(1) bilan yonib-o'chadi.

Yechim
html
<style>
  body { padding: 1rem; }
  .shior {
    width: 33ch;
    overflow: hidden;
    white-space: nowrap;
    border-right: 3px solid #2f6b3a;
    font-family: monospace;
    font-size: 1.1rem;
    color: #2f6b3a;
  }
  @keyframes yozish {
    from { width: 0; }
  }
  @keyframes kursor {
    50% { border-color: transparent; }
  }
  @media (prefers-reduced-motion: no-preference) {
    .shior {
      animation:
        yozish 3s steps(33),
        kursor 0.8s steps(1) 4;
    }
  }
</style>
<p class="shior">Choyxona «Bahor» — xush kelibsiz!</p>
  • yozish da faqat from — oxiri elementning o'z eni 33ch. steps(33) — har belgi uchun bitta sakrash.
  • Kursor 4 marta miltillaydi (3.2 soniya) va to'xtaydi — sekundiga 3 martadan kam, bu xavfsiz. infinite qilmang.
  • Ehtiyot bo'ling: width animatsiyasi — layout xususiyati. Bitta qisqa sarlavha uchun bu mayda narsa, lekin sahifaning katta qismida bunday qilmang.
  • Ekran o'quvchi matnni darhol to'liq o'qiydi — animatsiya faqat ko'zga.

3-mashq (qiyin): "Yuborilmoqda" nuqtalari

Bron formasi yuborilayotganda tugma ostida uchta nuqta navbat bilan sakraydi. Talablar:

  1. Nuqtalar — uchta span, animatsiya bitta @keyframes bilan, kechikish --i o'zgaruvchisidan.
  2. Har nuqta 0.3 soniyada tepaga (-0.5rem) chiqib tushadi, nuqtalar orasidagi kechikish — 0.15 s.
  3. To'xtovsiz ishlaydi (yuborish odatda 1–2 soniya), lekin harakatni kamaytirgan foydalanuvchida nuqtalar sakramaydi — o'rniga sekin xiralashib-yorishadi.
  4. Ekran o'quvchi "Yuborilmoqda" ni eshitsin, nuqtalarni emas.
html
<p class="yuborilmoqda">
  Yuborilmoqda
  <span aria-hidden="true">
    <span></span><span></span><span></span>
  </span>
</p>

yuborilmoqda — namoyish nomi. Haqiqiy formada bu holatni JavaScript yoqadi — 09-qismda.

Ishora: alternate sakrashni "borib-kelish" qiladi. Reduced motion uchun alohida @keyframes yozing. Nuqtalar span — inline, transform uchun inline-block (2D transformlar).

Yechim
html
<style>
  body { padding: 1rem; font-family: system-ui, sans-serif; }
  .yuborilmoqda { color: #2f6b3a; font-weight: bold; }
  .yuborilmoqda span span {
    display: inline-block;
    width: 0.4rem;
    height: 0.4rem;
    margin-inline-start: 0.2rem;
    border-radius: 50%;
    background-color: currentColor;
  }
  .yuborilmoqda span span:nth-child(1) { --i: 0; }
  .yuborilmoqda span span:nth-child(2) { --i: 1; }
  .yuborilmoqda span span:nth-child(3) { --i: 2; }
  @keyframes sakrash {
    to { translate: 0 -0.5rem; }
  }
  @keyframes xiralash {
    to { opacity: 0.3; }
  }
  .yuborilmoqda span span {
    animation: xiralash 0.8s ease-in-out infinite alternate;
    animation-delay: calc(var(--i) * 0.15s);
  }
  @media (prefers-reduced-motion: no-preference) {
    .yuborilmoqda span span {
      animation-name: sakrash;
      animation-duration: 0.3s;
    }
  }
</style>
<p class="yuborilmoqda">
  Yuborilmoqda
  <span aria-hidden="true">
    <span></span><span></span><span></span>
  </span>
</p>
  • Asos — xiralashish, hamma uchun: opacity 1 ↔ 0.3, 0.8 soniyada — harakat emas, bosh aylantirmaydi.
  • Harakat ruxsat bo'lsa — faqat nom va davomiylik almashadi: animation-name: sakrash, 0.3s. Kechikish, takror va yo'nalish asosiy qoidadan qoladi — to'liq xususiyatlar bilan yozishning afzalligi.
  • infinite bu yerda to'g'ri: bu bezak emas, holat ko'rsatkichi va u ish tugashi bilan yo'qoladi. 5 soniyadan uzoq yuklanishda esa foydalanuvchiga matn bilan tushuntirish kerak.
  • aria-hidden="true" — nuqtalar ekran o'quvchidan yashirin, "Yuborilmoqda" so'zi qoladi. Haqiqiy formada holat o'zgarishini ekran o'quvchiga e'lon qilish — Jonli hududlar darsidagi aria-live ishi.

Portfolio'dagi skip link (Yakuniy loyiha) Tab bosilganda chap yuqori burchakda birdan paydo bo'ladi. Uni tepadan sirg'alib tushadigan qiling:

  1. .otish:focus holatida 0.2 soniyalik animatsiya: havola o'z bo'yidan tepada (-150%) boshlanib, joyiga tushsin.
  2. Faqat harakat ruxsat bo'lsa.
  3. Tekshiring: Tab → havola tushib chiqadi; Shift + Tab bilan chiqib, yana Tab — yana tushadimi?

Ishora: faqat from yetadi — oxiri havolaning o'z joyi. Animatsiya .otish:focus qoidasi ishga tushgan zahoti boshlanadi, chunki animation-name none dan yangi nomga o'zgaradi. @keyframes "2. O'zgaruvchilar va shrift" bo'limiga yoki animatsiya ishlatilgan joy yoniga yoziladi — faylda bitta joyni tanlang.

Yechim

"6. Afzalliklar va qurilma" bo'limiga — faqat harakat ruxsat bo'lganda:

css
/* Skip link tepadan sirg'alib tushadi (@keyframes darsi) */
@keyframes otish-kirish {
  from {
    translate: 0 -150%;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .otish:focus {
    animation: otish-kirish 0.2s ease-out;
  }
}

Chrome'da tekshirdik: havola fokuslanganda animatsiya boshlandi, 0.3 soniyalik o'lchovda (1 soniyaga cho'zib sinadik) u o'z bo'yining 82 foizi tepada edi. Fokus boshqa elementga o'tganda animatsiya o'chdi, qayta fokuslanganda — yana noldan boshlandi.

  • ease-out — paydo bo'lish: tez boshlanib, yumshoq to'xtaydi.
  • Nega forwards yo'q? Oxirgi holat — havolaning o'z joyi, u allaqachon .otish:focus qoidasida yozilgan.
  • Fokus halqasi animatsiya paytida ham ko'rinadi — outline havolaga ergashadi.
  • Nomi otish-kirish — otish klassidan olingan, portfolio faylida boshqa animatsiya bilan chalkashmaydi.

13. Real ishda

  • Yuklanish holatlari — spinner, nuqtalar, skeleton: deyarli hammasi @keyframes bilan (Micro-interaktsiyalar).
  • Tayyor kutubxonalar. Animate.css — tayyor @keyframes to'plami (bounce, fadeIn...). Ular ham shu darsdagi xususiyatlar bilan ishlaydi — ichini o'qiy olasiz.
  • JavaScript animatsiyalari. GSAP, Motion kabi kutubxonalar murakkab ketma-ketliklar uchun. Ular brauzerning Web Animations API siga tayanadi (kursda keyin, hozir bilish shart emas).
  • Dizayn tizimlari animatsiya nomlari, davomiylik va easing'ni token qilib saqlaydi (Dizayn tokenlari).
  • Intervyuda so'raladi: "Transition va animation farqi?", "animation-fill-mode: forwards nima qiladi?", "Animatsiya kaskadda qayerda turadi?", "Animatsiyani qanday qilib accessibility'ga mos qilasiz?"

Xulosa

  • @keyframes nom { from {} 50% {} to {} } — ssenariy; animation: nom 1s — uni elementga ulash.
  • Yozilmagan bosqich elementning o'z qiymatidan olinadi; !important ssenariy ichida ishlamaydi.
  • Qisqa yozuvda birinchi vaqt — davomiylik, ikkinchisi — kechikish; nom kalit so'zga o'xshamasin.
  • fill-mode: backwards — kutishda boshlang'ich holat, forwards — oxirgi holatda qolish, both — ikkalasi.
  • Bir nechta animatsiya — vergul bilan; animation-composition: add ularni elementning qiymatiga qo'shadi.
  • Kaskadda animatsiya oddiy qoidalardan kuchli, !important dan kuchsiz.
  • Bezak — 1–3 marta, miltillash yo'q, harakat — prefers-reduced-motion: no-preference ichida.

Keyingi dars: Kirish va chiqish animatsiyalari: @starting-style va height: auto — display: none dan paydo bo'lish va balandlikni auto gacha silliq ochishni JS'siz qilamiz.

Manbalar

  • MDN: "@keyframes", "animation", "Using CSS animations", "animation-composition", "offset-path", "animationend event", "Document.getAnimations()" — developer.mozilla.org
  • W3C: "CSS Animations Level 1", "Motion Path Module Level 1", "CSS Cascading and Inheritance Level 5" (kuchlar tartibi) — w3.org/TR
  • W3C WAI: "Understanding SC 2.2.2: Pause, Stop, Hide" va "SC 2.3.1: Three Flashes" — w3.org/WAI/WCAG22/Understanding
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS animatsiya: @keyframes va animation xususiyatlari — IlmHamroh