IlmHamroh
JavaScript Full-stack/6-qism. CSS: harakat, zamonaviy CSS va dizayn14/57-dars17 daqiqa
Mundarija (35)

CSS View Transitions: sahifa va holatlar orasida silliq o'tish

Qisqacha: View Transitions — brauzer sahifaning eski ko'rinishini "suratga oladi", o'zgarishni qo'llaydi, yangisini ham suratga oladi va ikkalasi orasida o'zi animatsiya yasaydi. Bitta sahifa ichida u document.startViewTransition(() => ...) bilan ishga tushadi, sahifalar orasida esa ikkala sahifadagi @view-transition { navigation: auto; } bilan. view-transition-name bergan elementingiz eski joyidan yangisiga "ko'chib" o'tadi. Bitta sahifadagi o'tishlar yangi Baseline, sahifalararo o'tishlar esa hali Firefox'da yo'q.

Bu darsda

  • View Transition qanday ishlashini — "ikki surat va ular orasidagi animatsiya" — tushuntira olasiz.
  • view-transition-name bilan elementni bir joydan boshqasiga silliq ko'chirasiz.
  • ::view-transition-old, ::view-transition-new va ::view-transition-group ni CSS'da sozlaysiz.
  • view-transition-class, match-element va o'tish turlari nima uchun kerakligini bilasiz.
  • Ko'p sahifali saytga @view-transition qo'shasiz va uni harakat sozlamasiga bo'ysundirasiz.

Oldin bilishingiz kerak: @keyframes va animation, Brauzer mosligi va @supports, prefers-reduced-motion, Ko'p sahifali sayt tuzilmasi.

1. Nega bu kerak?

O'tgan darsda scroll-driven animatsiyalar bilan skrollga harakat bog'ladik. Bugungi mavzu — holat o'zgarishi.

«Bahor» saytida ikki joy bor. Birinchisi: menyu sahifasida "Narx bo'yicha saralash" tugmasi. Bosilganda taomlar ro'yxati bir zumda boshqa tartibga "sakraydi". Mehmon osh qayerga ketganini ko'rmaydi — ko'zi ro'yxatni qaytadan o'qib chiqishga majbur.

Ikkinchisi: bosh sahifadan menyu sahifasiga o'tish. Havola bosiladi, ekran bir lahza oqarib, yangi sahifa paydo bo'ladi. Sayt sarlavhasi ikkala sahifada ham bir xil joyda turibdi, lekin u ham "o'chib-yonadi".

Telefon ilovalarida bunday bo'lmaydi: ro'yxat elementlari yangi joyiga suzib boradi, ekranlar bir-biriga silliq o'tadi. Veb-saytda buni qilish ilgari juda qiyin edi. Har elementning eski va yangi joyini JavaScript bilan o'lchab, ular orasida animatsiyani qo'lda yasash kerak edi.

View Transitions API bu ishni brauzerga topshiradi.

2. Qanday ishlaydi: ikki surat

2.1 Jarayon

Bitta o'tish shunday bosqichlardan iborat:

sequenceDiagram
  participant K as Kod
  participant B as Brauzer
  K->>B: startViewTransition(yangila)
  B->>B: Eski holatni suratga oladi
  B->>K: yangila() ni chaqiradi
  K->>B: DOM o'zgardi
  B->>B: Yangi holatni suratga oladi
  B->>B: Eski → yangi animatsiya

Nimaga qarang: animatsiya paytida foydalanuvchi haqiqiy sahifani emas, suratlarni ko'radi. Eski surat asta so'nadi, yangisi asta paydo bo'ladi. Haqiqiy DOM (brauzer xotirasidagi sahifa daraxti — DevTools'ning Elements panelida ko'radiganingiz) esa allaqachon yangi holatda. Xuddi to'y videosidagi kadrlar almashishi kabi: bir kadr so'nib, ikkinchisi chiqadi.

Sukut bo'yicha animatsiya — crossfade (eski surat shaffoflashadi, yangisi paydo bo'ladi). Chrome'da o'lchadik: uning davomiyligi 0,25 soniya.

2.2 Birinchi o'tish

Bitta sahifa ichidagi o'tishni faqat JavaScript boshlaydi — CSS'da "bosilganda o'tish yasa" degan buyruq yo'q. JavaScript'ni 08-qismdan o'rganasiz, classList va stillar darsida esa sahifani boshqarishni. Hozir faqat ko'rinishini tanishtiramiz — bu qatorlarni aynan ko'chirsangiz yetadi:

html
<style>
  body { font-family: system-ui, sans-serif; }
  .taom-karta {
    view-transition-name: osh-karta;
    width: 160px;
    padding: 12px;
    border-radius: 12px;
    background-color: #e8f1ec;
  }
  .taom-karta p { display: none; }
  .katta .taom-karta {
    width: 320px;
    background-color: #fffaf0;
    border: 2px solid #2f6b3a;
  }
  .katta .taom-karta p { display: block; }
  button { margin-block-end: 12px; font: inherit; }
</style>
<button type="button">Batafsil</button>
<article class="taom-karta">
  <h3>Osh</h3>
  <p>Toshkent oshi: guruch, sabzi, qo'y go'shti,
    no'xat. 35 000 so'm.</p>
</article>
<script>
  const tugma = document.querySelector("button");
  tugma.addEventListener("click", () => {
    const yangila = () => document.body.classList.toggle("katta");
    if (!document.startViewTransition) {
      yangila();
      return;
    }
    document.startViewTransition(yangila);
  });
</script>

Nimaga qarang: "Batafsil" ni bosing — karta yon tomonga cho'zilib, ichida matn paydo bo'ladi. Bu bir zumda emas, chorak soniyada, silliq bo'ladi. Yana bosing — karta orqaga kichrayadi.

Skriptni qatorma-qator o'qiymiz, sintaksisini yodlash shart emas:

  • yangila — sahifani o'zgartiradigan kichik funksiya (bir marta yozilib, keyin chaqiriladigan kod bo'lagi): body ga katta class'ini qo'shadi yoki olib tashlaydi. Qolgan hamma ishni CSS qiladi (.katta .taom-karta).
  • if (!document.startViewTransition) — "brauzer bu imkoniyatni bilmasa" — oddiygina yangila() va tamom. Eski brauzerda karta animatsiyasiz, lekin baribir kattalashadi.
  • document.startViewTransition(yangila) — "suratga ol, yangila ni bajar, yana suratga ol, animatsiya qil".

Ishni bo'lish qoidasi CSS o'zgaruvchilari 2 darsidagidek: JavaScript holatni almashtiradi, ko'rinishni CSS hal qiladi.

2.3 view-transition-name: "bu element — alohida aktyor"

Yuqoridagi kartada view-transition-name: osh-karta bor. U nima qildi?

Sukut bo'yicha brauzer butun sahifani bitta surat qilib oladi. Bu surat avtomatik root nomini oladi. Butun sahifa crossfade bo'ladi — karta ham, tugma ham birga so'nib-chiqadi.

view-transition-name beriladigan element esa alohida suratga olinadi. Brauzer eski sahifada ham, yangisida ham shu nomli elementni topadi va uning joyi hamda o'lchamini solishtiradi. So'ng suratni eski joyidan yangi joyiga "ko'chiradi" va o'lchamini silliq o'zgartiradi. Xuddi teatr sahnasi kabi: dekoratsiya (root) almashadi, nomi aytilgan aktyor (osh-karta) esa sahnaning bir chetidan boshqasiga yurib o'tadi.

Diqqat: Nom sahifada yagona bo'lishi kerak. Ikkita elementga bir xil nom bersangiz, o'tish umuman bo'lmaydi. Chrome konsolida shunday xato chiqadi:

Unexpected duplicate view-transition-name: osh-karta

Tarjimasi: "Kutilmagan takroriy view-transition-name: osh-karta". O'zgarishning o'zi (yangila) baribir bajariladi — faqat animatsiyasiz. Chrome'da tekshirdik.

Tekshirib ko'ring: Menyuda 12 ta taom kartasi bor. Hammasiga view-transition-name: taom yozildi. Nima bo'ladi?

Javob

O'tish ishlamaydi: nom yagona emas, konsolda Unexpected duplicate view-transition-name: taom xatosi. Sahifa baribir yangilanadi, lekin animatsiyasiz. Har kartaga alohida nom kerak (taom-osh, taom-manti) — yoki keyinroq ko'radigan match-element qiymati.

3. Animatsiyani sozlash: pseudo-elementlar daraxti

3.1 Daraxt

O'tish paytida brauzer sahifa ustida vaqtinchalik pseudo-elementlar daraxtini quradi:

text
::view-transition
├─ ::view-transition-group(root)
│  └─ ::view-transition-image-pair(root)
│     ├─ ::view-transition-old(root)
│     └─ ::view-transition-new(root)
└─ ::view-transition-group(osh-karta)
   └─ ::view-transition-image-pair(osh-karta)
      ├─ ::view-transition-old(osh-karta)
      └─ ::view-transition-new(osh-karta)
  • ::view-transition-group(nom) — nomli elementning "ramkasi". U eski joy va o'lchamdan yangisiga harakatlanadi.
  • ::view-transition-old(nom) — eski surat, sukut bo'yicha so'nadi.
  • ::view-transition-new(nom) — yangi surat, sukut bo'yicha paydo bo'ladi.
  • ::view-transition-image-pair(nom) — ikki suratni ustma-ust ushlab turadigan o'ram.

Bular oddiy pseudo-elementlar — ularga CSS yoziladi. (*) — hamma nomlar uchun.

3.2 Davomiylik va xarakter

css
::view-transition-group(osh-karta) {
  animation-duration: 0.4s;
  animation-timing-function: ease-out;
}

Chrome'da o'lchadik: group ga 2 soniya berganimizda, uning ichidagi old va new animatsiyalari ham 2 soniya bo'ldi. Brauzerning o'z stilida ular davomiylikni guruhdan meros oladi — bitta joyga yozish yetadi.

3.3 O'z animatsiyangiz: siljib almashish

Crossfade o'rniga eski ko'rinish chapga ketib, yangisi o'ngdan kirsin. Buning uchun old va new ga o'z @keyframesingiz beriladi:

html
<style>
  body { font-family: system-ui, sans-serif; }
  .panel {
    view-transition-name: panel;
    padding: 16px;
    border-radius: 12px;
    background-color: #e8f1ec;
  }
  .kechki .panel { background-color: #fffaf0; }
  .kechki .kun, .panel .kech { display: none; }
  .kechki .panel .kech { display: block; }
  @keyframes chapga {
    to { transform: translateX(-100%); opacity: 0; }
  }
  @keyframes ongdan {
    from { transform: translateX(100%); opacity: 0; }
  }
  ::view-transition-old(panel) {
    animation: chapga 0.3s ease-in both;
  }
  ::view-transition-new(panel) {
    animation: ongdan 0.3s ease-out both;
  }
  button { margin-block-end: 12px; font: inherit; }
</style>
<button type="button">Kunduzgi / kechki menyu</button>
<section class="panel">
  <p class="kun">Kunduzi: osh, lag'mon, ko'k choy.</p>
  <p class="kech">Kechqurun: shashlik, manti, qora choy.</p>
</section>
<script>
  const tugma = document.querySelector("button");
  tugma.addEventListener("click", () => {
    const yangila = () => document.body.classList.toggle("kechki");
    if (!document.startViewTransition) {
      yangila();
      return;
    }
    document.startViewTransition(yangila);
  });
</script>

Nimaga qarang: tugmani bosing — kunduzgi menyu paneli chapga surilib ketadi, kechkisi o'ngdan kirib keladi. Qaytadan bossangiz, yana o'sha yo'nalishda: har safar chapga. Bir muammo: "orqaga" qaytganda ham harakat chapga. Buni "O'tish turlari" bo'limida tuzatamiz.

4. Ko'p elementli o'tishlar

4.1 view-transition-class: bitta qoida — ko'p element

12 ta taom kartasiga 12 ta nom kerak (taom-osh, taom-manti...). Ularning har biriga alohida ::view-transition-group(taom-osh) qoidasi yozish — azob. view-transition-class ularni guruhlaydi:

css
.taom-karta {
  view-transition-class: taom;
}

::view-transition-group(.taom) {
  animation-duration: 0.5s;
}

Nuqta bilan yozilgan (.taom) — "taom class'idagi hamma o'tish guruhlari". Bu oddiy HTML class emas, faqat o'tishlar uchun alohida nom.

4.2 match-element: nomni brauzer o'ylab topsin

Yagona nom har kartaga kerak, lekin ularni qo'lda yozish noqulay. view-transition-name: match-element — "bu elementga brauzerning o'zi yagona nom bersin". Brauzer DOM'dagi elementning o'zini eslab qoladi: saralashda element boshqa joyga ko'chsa, u o'sha elementni topadi.

html
<style>
  body { font-family: system-ui, sans-serif; }
  ul {
    display: grid;
    gap: 8px;
    padding: 0;
    list-style: none;
  }
  li {
    view-transition-name: match-element;
    view-transition-class: taom;
    display: flex;
    justify-content: space-between;
    padding: 10px 14px;
    border-radius: 8px;
    background-color: #e8f1ec;
  }
  ::view-transition-group(.taom) {
    animation-duration: 0.5s;
  }
  .narx { color: #b4461a; font-weight: bold; }
  button { font: inherit; }
</style>
<button type="button">Narx bo'yicha saralash</button>
<ul>
  <li data-narx="35000">Osh <span class="narx">35 000</span></li>
  <li data-narx="5000">Ko'k choy <span class="narx">5 000</span></li>
  <li data-narx="30000">Manti <span class="narx">30 000</span></li>
  <li data-narx="28000">Lag'mon <span class="narx">28 000</span></li>
</ul>
<script>
  const royxat = document.querySelector("ul");
  let osish = true;
  document.querySelector("button").addEventListener("click", () => {
    const yangila = () => {
      const taomlar = [...royxat.children].sort((a, b) =>
        osish ? a.dataset.narx - b.dataset.narx
              : b.dataset.narx - a.dataset.narx);
      royxat.append(...taomlar);
      osish = !osish;
    };
    if (!document.startViewTransition) {
      yangila();
      return;
    }
    document.startViewTransition(yangila);
  });
</script>

Nimaga qarang: tugmani bosing — ko'k choy ro'yxat tepasiga suzib chiqadi, osh esa pastga tushadi. Har qator o'z yo'li bilan, yarim soniyada. Yana bossangiz, tartib teskari bo'ladi. Qatorlar sakramaydi — ko'z har taomni kuzatib boradi.

data-narx — Global atributlar darsidagi o'z ma'lumot atributi. Skriptdagi saralash qatorlarini tushunish shart emas — ular 08-qismda keladi.

Diqqat: match-element bitta sahifa ichida ishlaydi. Sahifalar orasidagi o'tishda eski va yangi sahifa — boshqa-boshqa DOM, element "o'zi" yo'q. U yerda nomni qo'lda yozing.

5. O'tish turlari (types)

Kunduzgi/kechki menyu misolidagi muammoni eslang: "orqaga" ham chapga siljidi. O'tish turi (type) — o'tishga qo'yiladigan yorliq. CSS unga qarab turli animatsiya tanlaydi:

js
document.startViewTransition({
  update: yangila,
  types: ["oldinga"],
});

Avvalgi startViewTransition(yangila) dan farqi: endi qavs ichida ikki qismli sozlama. update — o'sha yangila, types — yorliqlar ro'yxati (kvadrat qavs JavaScript'da ro'yxatni bildiradi). Bu yerda bitta yorliq bor: "oldinga".

O'tish davom etayotgan paytda CSS'dagi :active-view-transition-type() pseudo-klassi html elementiga mos keladi. Qavs ichiga yorliq nomi yoziladi:

css
html:active-view-transition-type(oldinga) {
  &::view-transition-old(panel) { animation-name: chapga; }
  &::view-transition-new(panel) { animation-name: ongdan; }
}

html:active-view-transition-type(orqaga) {
  &::view-transition-old(panel) { animation-name: onga; }
  &::view-transition-new(panel) { animation-name: chapdan; }
}

Bu yerda Native CSS nesting darsidagi & ishlatildi. Tugma bosilganda JavaScript turni tanlaydi: kechki menyuga — "oldinga", kunduzgiga — "orqaga". Pastdagi 3-mashqda to'liq yozasiz.

6. Sahifalar orasida: @view-transition

6.1 Ikki qator CSS

Endi eng qiziq qism: bosh sahifadan menyuga havola orqali o'tish. Bu yerda JavaScript umuman kerak emas. Ikkala sahifaning CSS'iga:

css
@view-transition {
  navigation: auto;
}

"Bu sahifaga (yoki undan) oddiy havola orqali o'tilsa, View Transition yasa." Ikkala sahifada ham bo'lishi shart: chiqayotgan sahifa ham, kirayotgan ham rozi bo'lishi kerak. «Bahor» bitta asosiy.css ga ega — bitta joyga yozish yetadi.

Natija — butun sahifa crossfade: oq chaqnash o'rniga eski sahifa yumshoq so'nadi, yangisi chiqadi. Sarlavha joyida qolsin desangiz, unga nom bering:

css
body > header {
  view-transition-name: sarlavha;
}

Endi har sahifada sarlavha "bir xil element" deb tanilgan — u joyida qoladi yoki yangi o'lchamiga silliq o'tadi, faqat qolgan kontent almashadi.

6.2 Shartlar

  • Bir xil origin. Ikkala sahifa bitta saytda bo'lsin (Origin va Same-Origin Policy): 127.0.0.1:5500 ichida, login.github.io ichida. Boshqa saytga havola — oddiy o'tish.
  • Oddiy navigatsiya. Havola bosilishi, orqaga/oldinga tugmalari. Manzil satriga qo'lda yozish va sahifani yangilash hisoblanmaydi.
  • Tez yuklanish. Yangi sahifa juda sekin ochilsa, brauzer o'tishni tashlab yuboradi.

Chrome'da tekshirdik: Live Server'ga o'xshash lokal serverda index.html dan menyu.html ga havola bosilganda yangi sahifaga o'tish animatsiyasi yetib keldi.

6.3 Natija oynasi bu yerda nega yordam bermaydi

Darslardagi natija oynasi — bitta hujjat. Unda havolalar boshqa sahifani ochmaydi: sahifangiz bexosdan tark etilmasligi uchun sayt ularni to'xtatadi. Shuning uchun sahifalararo o'tishni bu yerda ko'rsata olmaymiz — uni o'z kompyuteringizda, ikki fayl bilan sinab ko'rasiz (2-mashq). Bitta sahifa ichidagi o'tishlar esa yuqoridagi natija oynalarida to'liq ishlaydi.

7. Harakatni kamaytirish va brauzer mosligi

7.1 prefers-reduced-motion

Sahifa bo'ylab "uchib o'tadigan" elementlar — aynan harakat etikasi darsida gaplashgan xavfli harakat. Ikki yo'l bor. Sahifalararo o'tishni faqat harakat kamaytirilmagan bo'lsa yoqish:

css
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

Bitta sahifa ichidagi o'tishlarni esa animatsiyasiz qoldirish:

css
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

Chrome'da prefers-reduced-motion: reduce bilan tekshirdik: o'tish paytida birorta animatsiya yaratilmadi va o'tish 30 millisekundga yetmay tugadi. !important bu yerda asosli istisno (Kaskad): animatsiyani qayerda yozgan bo'lsangiz ham, foydalanuvchi sozlamasi yutsin.

7.2 Baseline holati

Baseline ma'lumotiga ko'ra:

Imkoniyat Holat
startViewTransition, view-transition-name, pseudo-elementlar Yangi Baseline, 2025-yil oktabr
view-transition-class, match-element Yangi Baseline, 2025-yil oktabr
O'tish turlari (types) Yangi Baseline, 2026-yil yanvar
Sahifalararo (@view-transition) Baseline emas

Bitta sahifa ichidagi o'tishlarni oxirgi bo'lib Firefox 144 qo'shdi — yangi, eski brauzerlarda yo'q. Sahifalararo o'tishlar Chrome va Edge'da 126-versiyadan, Safari'da 18.2 dan bor, Firefox'da esa hali yo'q.

Bu xavfli emas. Yuqoridagi JavaScript startViewTransition yo'qligini tekshiradi va oddiy yangilanishni bajaradi. @view-transition ni tushunmagan brauzer esa uni jimgina tashlaydi — sahifalar odatdagidek ochiladi. Ya'ni View Transitions — toza progressive enhancement: bor joyda chiroyli, yo'q joyda oddiy.

8. Freymvorklarda

React'da o'tishlar uchun <ViewTransition> komponenti bor — u ichkarida xuddi shu API'ni chaqiradi. Next.js kabi freymvorklar ham sahifalar orasidagi o'tishni shu API bilan ulaydi. React'ni kursda alohida o'rganamiz — hozir bilish shart emas; tafsiloti React'da View Transitions darsida. JavaScript tomonidagi imkoniyatlar (o'tish tugashini kutish, uni o'tkazib yuborish) — Web Animations API darsida.

9. Ko'p uchraydigan xatolar

9.1 Takroriy nom

Konsolda Unexpected duplicate view-transition-name — ikki element bir xil nomda. Ko'pincha bitta class'ga nom yozilgani uchun: .taom-karta { view-transition-name: karta; }. Tuzatish: har elementga alohida nom yoki match-element.

9.2 Faqat bitta sahifaga yozilgan @view-transition

Bosh sahifadan menyuga o'tish animatsiyasiz. Sabab: @view-transition faqat bosh sahifaning CSS'ida, menyu sahifasi esa boshqa faylni ulaydi. Tuzatish: ikkala sahifada ham bo'lsin — umumiy CSS faylga yozing.

9.3 Nomli element "cho'ziladi"

Karta kattalashganda matn o'tish paytida g'alati cho'zilib ko'rinadi. Sabab: ::view-transition-old va new — rasm (surat), guruh o'lchami o'zgarganda ular ham cho'ziladi. Tuzatish: qisqa davomiylik (0,2–0,4 s) — ko'z cho'zilishni sezmay qoladi. Eni ham, bo'yi ham keskin o'zgaradigan elementlar uchun MDN'ning "View Transition API" qo'llanmasida suratlarni cho'zmasdan kesib ko'rsatish usullari bor — ular keyingi darajadagi mavzu.

9.4 display: none elementga nom

Yashirin elementda nom bor-u, lekin u o'tishda qatnashmaydi — ko'rinmas element suratga olinmaydi. Bu xato emas, lekin kutilmagan bo'lishi mumkin: element eski holatda yo'q, yangisida bor bo'lsa, u shunchaki paydo bo'ladi (faqat new surati).

10. Mashqlar

Mashqlarni kurs/mashqlar/06/ papkasida bajaring.

1-mashq (oson): tezroq crossfade

Butun sahifa crossfade'i 0,15 soniya bo'lsin, taom-karta nomli element esa 0,5 soniyada ko'chsin.

Ishora: root — butun sahifa suratining nomi.

Yechim
css
::view-transition-group(root) {
  animation-duration: 0.15s;
}

::view-transition-group(taom-karta) {
  animation-duration: 0.5s;
}

old va new davomiylikni guruhdan oladi — ularga alohida yozish shart emas.

2-mashq (o'rta): ikki sahifa o'rtasida

kurs/mashqlar/06/otish/ papkasida ikki fayl yarating: index.html (sarlavha "Choyxona «Bahor»", "Menyu" havolasi) va menyu.html (xuddi shu sarlavha, taomlar ro'yxati, "Bosh sahifa" havolasi). Ikkalasi bitta asosiy.css ni ulasin.

  1. Sahifalar orasida o'tish silliq bo'lsin — faqat harakat kamaytirilmagan bo'lsa.
  2. Sarlavha o'tishda joyida qolsin.
  3. Live Server bilan oching va Chrome'da tekshiring. Firefox'da nima bo'ladi?

Ishora: «Sahifalar orasida» bo'limi. Faylni to'g'ridan-to'g'ri (ikki marta bosib) ochmang — Live Server manzili 127.0.0.1:5500 bo'lsin.

Yechim

asosiy.css:

css
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

header {
  view-transition-name: sarlavha;
}

index.html (qisqartirilgan):

html
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Choyxona «Bahor»</title>
  <link rel="stylesheet" href="asosiy.css">
</head>
<body>
  <header><h1>Choyxona «Bahor»</h1></header>
  <main>
    <p><a href="menyu.html">Menyu</a></p>
  </main>
</body>

menyu.html da xuddi shu head va header, main ichida taomlar ro'yxati va <a href="index.html">Bosh sahifa</a>.

Chrome'da havolani bossangiz, sarlavha qimirlamaydi, pastdagi kontent yumshoq almashadi. "Orqaga" tugmasi ham silliq. Firefox'da sahifalar odatdagidek, animatsiyasiz ochiladi — hech narsa buzilmaydi.

3-mashq (qiyin): yo'nalishli o'tish

Kunduzgi/kechki menyu misolini tuzating: kechki menyuga o'tganda panel chapga ketib, yangisi o'ngdan kirsin; kunduzgiga qaytganda — teskari.

Ishora: «O'tish turlari» bo'limi. Qaysi tur kerakligini JavaScript body da kechki class'i bor-yo'qligiga qarab tanlaydi: document.body.classList.contains("kechki"). To'rtta @keyframes kerak: chapga, ongdan, onga, chapdan.

Yechim
html
<style>
  body { font-family: system-ui, sans-serif; }
  .panel {
    view-transition-name: panel;
    padding: 16px;
    border-radius: 12px;
    background-color: #e8f1ec;
  }
  .kechki .panel { background-color: #fffaf0; }
  .kechki .kun, .panel .kech { display: none; }
  .kechki .panel .kech { display: block; }
  @keyframes chapga { to { translate: -100%; opacity: 0; } }
  @keyframes ongdan { from { translate: 100%; opacity: 0; } }
  @keyframes onga { to { translate: 100%; opacity: 0; } }
  @keyframes chapdan { from { translate: -100%; opacity: 0; } }
  ::view-transition-group(panel) { animation-duration: 0.3s; }
  html:active-view-transition-type(oldinga) {
    &::view-transition-old(panel) { animation-name: chapga; }
    &::view-transition-new(panel) { animation-name: ongdan; }
  }
  html:active-view-transition-type(orqaga) {
    &::view-transition-old(panel) { animation-name: onga; }
    &::view-transition-new(panel) { animation-name: chapdan; }
  }
  button { margin-block-end: 12px; font: inherit; }
</style>
<button type="button">Kunduzgi / kechki menyu</button>
<section class="panel">
  <p class="kun">Kunduzi: osh, lag'mon, ko'k choy.</p>
  <p class="kech">Kechqurun: shashlik, manti, qora choy.</p>
</section>
<script>
  const tugma = document.querySelector("button");
  tugma.addEventListener("click", () => {
    const yangila = () => document.body.classList.toggle("kechki");
    if (!document.startViewTransition) {
      yangila();
      return;
    }
    const kechkigami = !document.body.classList.contains("kechki");
    document.startViewTransition({
      update: yangila,
      types: [kechkigami ? "oldinga" : "orqaga"],
    });
  });
</script>
  • translate — 2D transformlar darsidagi alohida xususiyat; transform bilan bir xil ishlaydi.
  • kechkigami o'zgarishdan oldin hisoblanadi: hozir kechki yo'q bo'lsa, demak kechkiga ketyapmiz — "oldinga".
  • Eski Safari va Firefox'da types hali bo'lmasligi mumkin (2026-yil yanvarida Baseline bo'lgan). Bunday brauzerda turlar e'tiborsiz qoladi va sukut bo'yicha crossfade o'ynaydi.

4-mashq: Portfolio qadami — sahifalar orasida silliq o'tish

Portfolio — 6 sahifali sayt, hamma sahifa bitta asosiy.css ni ulaydi. Uni sahifalararo o'tishga tayyorlang:

  1. Havolalar orqali o'tish silliq bo'lsin — faqat harakat kamaytirilmagan bo'lsa.
  2. Header (ism va menyu) o'tishda joyida qolsin.
  3. Bitta sahifa ichidagi o'tishlarni (kelajakda JavaScript bilan qo'shiladi) ham harakat sozlamasiga bo'ysundiring.
  4. Live Server'da bosh sahifa → loyihalar → aloqa → orqaga bo'ylab yurib chiqing. 404.html da ham tekshiring (u /assets/css/asosiy.css ni ulaydi). So'ng npm run check va qayta deploy.

Ishora: header'ga selektor — body > header. 3-band — «prefers-reduced-motion» bo'limidagi ikkinchi parcha.

Yechim

asosiy.css ning «Umumiy» qismiga:

css
/* Sahifalar orasida silliq o'tish (View Transitions darsi).
   Firefox tushunmaydi — oddiy o'tadi */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

/* Header har sahifada "bitta element" — joyida qoladi */
body > header {
  view-transition-name: sayt-sarlavhasi;
}
  • Hamma sahifa bitta faylni ulaydi — shuning uchun «Bitta sahifaga yozilgan» xatosi bu yerda bo'lmaydi.
  • Header'ning ichi sahifadan sahifaga faqat aria-current havolasi bilan farq qiladi. O'tishda eski va yangi header ustma-ust crossfade bo'ladi — qalin "joriy sahifa" belgisi yangi havolaga yumshoq ko'chadi.
  • GitHub Pages'dagi portfolio bitta origin (login.github.io) — shart bajarilgan. Tashqi havolalar (Telegram, GitHub) odatdagidek ochiladi.

Chrome'da tekshirganda DevTools → Animations panelida o'tishni sekinlashtirib ko'rish mumkin: u yerda ::view-transition animatsiyalari ro'yxati chiqadi.

11. Real ishda

  • Ro'yxat va filtrlar — do'kon katalogida saralash, kartani to'liq ekranga ochish ("kartadan sahifaga"). Ilgari FLIP deb ataladigan qo'lda hisoblash usuli yoki animatsiya kutubxonalari kerak edi.
  • Ko'p sahifali saytlar — blog, hujjat saytlari, landing'lar: JavaScript freymvorkisiz ham "ilova kabi" o'tishlar.
  • React va Next.js — <ViewTransition> komponenti orqali, ichkarida shu API.
  • Intervyuda: "View Transitions API qanday ishlaydi?" — eski va yangi holat suratga olinadi, pseudo-elementlar daraxti animatsiya qilinadi, DOM esa darhol yangilanadi.

Xulosa

  • View Transition — eski va yangi holat suratlari orasidagi animatsiya; brauzer uni o'zi yasaydi, sukut bo'yicha 0,25 s crossfade.
  • Bitta sahifada — document.startViewTransition(yangila), doim if (!document.startViewTransition) zaxirasi bilan.
  • view-transition-name elementni alohida "aktyor" qiladi; nom yagona bo'lishi shart. Ko'p element uchun — match-element va view-transition-class.
  • ::view-transition-group/old/new — oddiy pseudo-elementlar: davomiylik va @keyframes ularga yoziladi; yo'nalish uchun — o'tish turlari.
  • Sahifalararo — ikkala sahifada @view-transition { navigation: auto; }, bir xil origin; hali Firefox'da yo'q, lekin hech narsa buzilmaydi.
  • Harakat kamaytirilganda — @view-transition ni o'chiring va pseudo-elementlarga animation: none.

Keyingi dars: Top layer: dialog va popover'ni stillash — modal oyna va popover'ning pardasi, ochilish va yopilish animatsiyasini CSS'da boshqaramiz.

Manbalar

  • MDN: "View Transition API", "Document.startViewTransition()", "view-transition-name", "view-transition-class", "@view-transition", "::view-transition-group()", ":active-view-transition-type()" — developer.mozilla.org
  • W3C: "CSS View Transitions Module Level 1" va "Level 2" — w3.org/TR/css-view-transitions-1
  • web-features (Baseline ma'lumotlari): "view-transitions", "view-transition-class", "active-view-transition", "cross-document-view-transitions" — github.com/web-platform-dx/web-features
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS View Transitions: sahifa va holatlar orasida silliq o'tish — IlmHamroh