IlmHamroh
JavaScript Full-stack/6-qism. CSS: harakat, zamonaviy CSS va dizayn5/57-dars20 daqiqa
Mundarija (31)

CSS @starting-style: kirish va chiqish animatsiyalari, display: none va height: auto

Qisqacha: display: none dan chiqqan element uchun transition ishlamaydi — uning "oldingi" holati yo'q. @starting-style shu oldingi holatni yozadi: @starting-style { opacity: 0; }. Yo'qolishda display darhol none bo'lmasligi uchun transition: display 0.2s allow-discrete yoziladi. height: auto gacha silliq ochish uchun interpolate-size: allow-keywords yoki calc-size() (hozircha Chrome'da), hamma brauzerda esa grid-template-rows: 0fr → 1fr hiylasi ishlaydi.

Bu darsda

  • Nega display: none va height: auto transition'ga "bo'ysunmasligini" tushuntirasiz.
  • @starting-style bilan paydo bo'lish animatsiyasini JS'siz yozasiz — sahifa yuklanganda ham.
  • transition-behavior: allow-discrete bilan yo'qolishni silliq qilasiz.
  • Balandlikni auto gacha uch usulda ochasiz va qaysi brauzerda qaysi biri ishlashini bilasiz.
  • Qo'llab-quvvatlamaydigan brauzerda ham sahifa buzilmaydigan qilib yozasiz.

Oldin bilishingiz kerak: Transition va timing funksiyalari, @keyframes va animation, display va yashirish, Grid'ga kirish.

1. Nega bu kerak?

Transition darsida jadval tuzgan edik: display: block → none, height: 0 → auto — sakraydi. Bu CSS'ning eng eski "og'riqli joylari"dan ikkitasi edi.

Oddiy vaziyatlar:

  • «Bahor» saytida "Menyu" ustiga sichqoncha kelganda ichki ro'yxat chiqadi. U display: none bilan yashiringan — va birdan paydo bo'ladi, birdan yo'qoladi.
  • "Taom tarkibi" bo'limi bosilganda ochiladi. Uning balandligi matnga bog'liq — auto. Silliq ochib bo'lmaydi.

Yillar davomida buni JavaScript bilan qilishardi: balandlikni o'lchab, pikselga aylantirib, animatsiya tugagach display: none qo'yib. Kod uzun, xatoga moyil edi. 2024-yildan boshlab brauzerlarga buning CSS yechimlari keldi. Bu dars — ular haqida.

Bu darsdagi imkoniyatlarning ko'pchiligi yangi. Har birida qaysi brauzerda ishlashini aytamiz. Asosiy tamoyil — Brauzer mosligi darsidagi progressive enhancement: eski brauzerda element shunchaki sakrab paydo bo'ladi, hech narsa buzilmaydi.

2. Muammo: display: none dan paydo bo'lish

2.1 Transition'ga "qayerdan" kerak

Transition ikki qiymat orasidagi yo'l: eski va yangi. Element display: none bo'lganda brauzer uning uslubini umuman hisoblamaydi — u chizilmaydi, joy egallamaydi (display). Element chiqqan zahoti uning birinchi uslubi — darhol oxirgi uslub. "Eski qiymat" yo'q — transition boshlanmaydi.

Chrome'da tekshirdik: display: none va transition: opacity 1s bo'lgan elementga display: block beradigan class qo'shdik. Brauzer bitta ham transition yaratmadi — element darhol to'liq ko'rindi.

Xuddi shu sabab bilan sahifa yuklanganda ham transition ishlamaydi: yangi chizilgan elementning "oldingi" holati yo'q. Shuning uchun @keyframes darsida details ro'yxatini animatsiya bilan ochgan edik, transition bilan emas.

2.2 @starting-style: "oldingi" holatni yozamiz

@starting-style — elementning birinchi chizilishidan oldingi uslubi. Brauzer uni "eski qiymat" sifatida oladi va undan haqiqiy uslubga transition qiladi.

css
.aksiya {
  opacity: 1;
  transition: opacity 0.3s ease-out;
}

@starting-style {
  .aksiya {
    opacity: 0;
  }
}

O'qilishi: ".aksiya birinchi marta chizilganda — opacity: 0 dan boshla va 0.3 soniyada 1 ga o't".

Qachon "birinchi marta chizilish" bo'ladi?

  • Sahifa yuklanganda — har element uchun.
  • Element display: none dan chiqqanda.
  • JavaScript yangi element qo'shganda (09-qismda).

Chrome'da tekshirdik: @starting-style bilan yozilgan paragraf sahifa ochilishi bilan transition boshladi — 2 soniyalik o'tishning boshida opacity 0.24 edi. Ya'ni endi paydo bo'lish effektlarini @keyframes siz, oddiy transition bilan yozish mumkin.

Ikkinchi yozilishi — qoidaning ichida. Qoida ichiga boshqa blok yozish nesting (ichma-ich yozish) deyiladi; uni Native CSS nesting darsida to'liq o'rganamiz, hozir faqat shu shaklni ko'ring:

css
.aksiya {
  opacity: 1;
  transition: opacity 0.3s ease-out;

  @starting-style {
    opacity: 0;
  }
}

Chrome'da ikkalasi bir xil ishladi. Ichidagi shakl qisqaroq va tartib tuzog'idan xoli — pastda ko'ramiz.

Baseline ma'lumotiga ko'ra @starting-style 2024-yil avgustdan hamma asosiy brauzerda bor — bu yangi imkoniyat. Eski brauzer @starting-style blokini tashlab ketadi: element transition'siz, darhol paydo bo'ladi. Sahifa ishlayveradi.

2.3 Tuzoq: tartib va specificity

@starting-style ichidagi qoida oddiy kaskadda qatnashadi (Kaskad). U specificity'ni oshirmaydi. Shuning uchun:

css
/* ❌ Ishlamaydi */
@starting-style {
  .aksiya.ochiq {
    opacity: 0;
  }
}

.aksiya.ochiq {
  opacity: 1;
}

Ikkala selektor og'irligi bir xil, pastdagisi yutadi — boshlang'ich uslub ham opacity: 1 bo'lib qoladi. Chrome'da aynan shunday yozib tekshirdik: transition umuman yaratilmadi. Tuzatish: @starting-style blokini oddiy qoidadan keyin yozing yoki qoida ichiga joylang.

Tekshirib ko'ring: @starting-style blokida translate: 0 1rem yozildi, lekin elementning o'z qoidasida transition: opacity 0.3s — translate yo'q. Paydo bo'lishda nima bo'ladi?

Javob

Element 1rem pastda chizilmaydi — lekin sakrab joyiga ham chiqmaydi: translate transition ro'yxatida yo'q, brauzer uni darhol oxirgi qiymat bilan chizadi. @starting-style faqat transition'ga "eski qiymat" beradi, transition'ning o'zini yaratmaydi. Suzib chiqish uchun transition: opacity 0.3s, translate 0.3s kerak.

3. Muammo: display: none ga yo'qolish

3.1 Nega darhol yo'qoladi

Paydo bo'lish hal bo'ldi. Endi teskarisi: class olib tashlanadi, element display: none va opacity: 0 bo'lishi kerak. Transition bor — lekin Chrome'da o'lchadik: display o'sha zahoti none bo'ldi, element yo'qoldi, opacity ning transition'i esa hech kimga ko'rinmadi.

Sababi — display diskret xususiyat (Transition): oraliq qiymati yo'q, u darhol almashadi.

3.2 transition-behavior: allow-discrete

allow-discrete — "diskret xususiyatni ham transition ro'yxatiga qo'shishga ruxsat". Diskret xususiyat baribir silliq o'zgarmaydi, lekin endi qachon almashishini brauzer aqlli tanlaydi:

  • display: none ga ketayotganda — transition oxirida almashadi. Butun vaqt davomida element block bo'lib turadi va opacity xiralashishi ko'rinadi.
  • display: none dan chiqayotganda — transition boshida almashadi. Element darhol block, keyin @starting-style dan silliq paydo bo'ladi.

Bu Transition darsidagi visibility xulqiga o'xshaydi — faqat endi har qanday diskret xususiyat uchun.

Butun aylanishni bitta rasmda ko'ramiz:

flowchart LR
  A["Yopiq<br/>display: none"] -->|"ochish: display darhol block"| B["@starting-style<br/>opacity: 0"]
  B -->|"transition"| C["Ochiq<br/>opacity: 1"]
  C -->|"yopish: opacity 1 → 0"| D["Xiralashmoqda<br/>display hali block"]
  D -->|"oxirida display: none"| A

Nimaga qarang: display ikki marta almashadi — ochilishda boshida, yopilishda oxirida. Shuning uchun ikkala yo'nalishda ham xiralashish ko'rinadi.

css
.aksiya {
  display: none;
  opacity: 0;
  transition:
    opacity 0.3s ease-out,
    display 0.3s allow-discrete;
}

Ikki yozilishi bor: ro'yxatdagi xususiyat yoniga allow-discrete yoki alohida transition-behavior: allow-discrete. Chrome'da o'lchadik: allow-discrete bilan 1 soniyalik yo'qolishning o'rtasida display hali block va opacity 0.5 edi. allow-discrete siz — darhol none.

Brauzer holati (Baseline ma'lumotlari bo'yicha):

  • transition-behavior — 2024-yil avgustdan hamma asosiy brauzerda (yangi Baseline).
  • Lekin display ni o'tkazish hali Baseline emas: Chrome 117 va Safari 18 dan bor, Firefox'da yo'q. Firefox'da element xiralashmasdan darhol yo'qoladi — buziladigan narsa yo'q, faqat effekt ko'rinmaydi.

overlay ham diskret xususiyat — u dialog va popover'larning "eng ustki qatlam"da turishini boshqaradi. Uni Top layer darsida xuddi shu allow-discrete bilan ishlatamiz.

3.3 «Bahor»: ochiladigan menyu

«Bahor» sarlavhasidagi "Menyu" bandining ichki ro'yxati. Sichqoncha kelganda yoki klaviatura fokusi kirganda chiqadi:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-fon: #fffaf0;
    --qatlam-menyu: 20;
  }
  body { font-family: system-ui, sans-serif; }
  nav ul {
    display: flex;
    gap: 1rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  nav li { position: relative; }
  nav a {
    display: block;
    padding: 0.5rem;
    color: var(--rang-asosiy);
  }
  nav li ul {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: var(--qatlam-menyu);
    display: none;
    flex-direction: column;
    gap: 0;
    min-width: 10rem;
    border: 2px solid var(--rang-asosiy);
    border-radius: 0.5rem;
    background-color: var(--rang-fon);
    opacity: 0;
    transition:
      opacity 0.2s ease-out,
      display 0.2s allow-discrete;
  }
  nav li:hover > ul,
  nav li:focus-within > ul {
    display: flex;
    opacity: 1;

    @starting-style {
      opacity: 0;
    }
  }
  @media (prefers-reduced-motion: no-preference) {
    nav li ul {
      translate: 0 -0.5rem;
      transition:
        opacity 0.2s ease-out,
        translate 0.2s ease-out,
        display 0.2s allow-discrete;
    }
    nav li:hover > ul,
    nav li:focus-within > ul {
      translate: 0;

      @starting-style {
        translate: 0 -0.5rem;
      }
    }
  }
</style>
<nav aria-label="Asosiy menyu">
  <ul>
    <li><a href="#">Bosh sahifa</a></li>
    <li>
      <a href="#">Menyu</a>
      <ul>
        <li><a href="#">Taomlar</a></li>
        <li><a href="#">Ichimliklar</a></li>
        <li><a href="#">Shirinliklar</a></li>
      </ul>
    </li>
    <li><a href="#">Bron</a></li>
  </ul>
</nav>

Nimaga qarang: skrinshotda ichki ro'yxat ko'rinmaydi — display: none. Sichqonchani "Menyu" ga olib boring: ro'yxat biroz tepadan suzib, xiralikdan chiqadi. Sichqonchani olib keting — xuddi shunday silliq yo'qoladi va faqat oxirida display: none bo'ladi. Tab bilan "Menyu" ga kelsangiz ham ochiladi. Baseline ma'lumotiga ko'ra Firefox'da display o'tishi hali yo'q — u yerda yopilish darhol bo'ladi.

Kodni o'qiymiz:

  • Yopiq holat — asosiy qoidada: display: none, opacity: 0 va transition ro'yxati (display — allow-discrete bilan).
  • Ochiq holat — :hover va :focus-within da (Holat pseudo-klasslari). Uning ichida @starting-style — "ochilayotganda qayerdan boshlash".
  • Nega ikki joyda opacity: 0? Asosiy qoidadagisi — yopilishning maqsadi (qayerga xiralashish). @starting-style dagisi — ochilishning boshlanishi. Ular har xil vazifada.
  • Harakat bloki transition ro'yxatini to'liq takrorlaydi (Transition darsidagi tuzoq) va translate ni qo'shadi.
  • --qatlam-menyu — z-index darsidagi shkaladan: ro'yxat sahifa kontentining ustida.

Diqqat: Faqat hover'da ochiladigan menyu telefonda va ekran o'quvchida muammoli: bosish, aria-expanded va klaviatura boshqaruvi kerak. To'liq, accessible navbar'ni Navbar va mobil menyu darsida quramiz. Bu yerdagi misol — faqat animatsiya texnikasi.

4. Muammo: height: auto

4.1 Nega auto ga transition yo'q

height: 0 dan height: 200px ga transition — muammosiz. height: auto ga esa — sakraydi. Chrome'da tekshirdik: brauzer transition yaratmadi, balandlik darhol 84 piksel bo'ldi.

Sababi: auto — son emas, "mazmunga qarab" degan buyruq. Transition 0 va "mazmunga qarab" orasidagi yarim yo'lni hisoblay olmaydi — ular bir xil turdagi qiymatlar emas.

Uzoq yillar ishlatilgan hiyla — max-height:

css
/* ❌ Eski hiyla: ishlaydi, lekin yomon */
.tarkib {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s;
}

.ochiq .tarkib {
  max-height: 1000px; /* "yetarlicha katta" son */
}

Muammolari: haqiqiy balandlik 100 piksel bo'lsa, transition 1000 gacha "yuradi" — ochilish 0.03 soniyada tugaydi va yopilish 0.27 soniya kechikib boshlanadi. Mazmun 1000 dan uzun bo'lsa — kesiladi. Buni eski kodda uchratasiz — ishlatmang.

Endi uchta to'g'ri yo'lni ko'ramiz.

4.2 Hamma brauzerda: grid-template-rows: 0fr → 1fr

Grid qatorining o'lchami fr bilan berilsa, u son — va brauzer 0fr dan 1fr gacha oraliqni hisoblay oladi. Baseline ma'lumotiga ko'ra grid qatorlari va ustunlarini animatsiya qilish 2022-yil oktabrdan hamma asosiy brauzerda, 2025-yil apreldan keng tarqalgan Baseline.

Hiyla shunday: ota — bitta qatorli grid. Qator 0fr bo'lganda bola balandligi nolga siqiladi, 1fr da — to'liq mazmun balandligi (Grid'ga kirish):

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  .taom-karta {
    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; }
  .narx { margin: 0.25rem 0 0; color: var(--rang-urgu); }
  .ochiluvchi {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.3s ease-out;
  }
  .ochiluvchi > div {
    overflow: hidden;
  }
  .taom-karta:hover .ochiluvchi,
  .taom-karta:focus-within .ochiluvchi {
    grid-template-rows: 1fr;
  }
  .ochiluvchi p { margin: 0.5rem 0 0; }
</style>
<article class="taom-karta" tabindex="0">
  <h3 class="taom-nomi">Osh</h3>
  <p class="narx">35 000 so'm</p>
  <div class="ochiluvchi">
    <div>
      <p>Tarkibi: guruch, sabzi, piyoz, mol go'shti, zira.</p>
      <p>Tayyorlash: 2 soat, qozonda.</p>
    </div>
  </div>
</article>

Nimaga qarang: skrinshotda karta faqat nom va narxdan iborat — tarkib bo'limi 0fr qatorida, bo'yi nol. Sichqonchani kartaga olib boring (yoki Tab bilan fokuslang): karta pastga silliq cho'ziladi va tarkib ochiladi. Qancha matn bo'lsa ham, karta aynan uning balandligigacha ochiladi.

Uch shart:

  • Ichki div shart. Grid qatori bolaning balandligini siqadi; ichidagi mazmun esa overflow: hidden bilan kesiladi. Usiz matn qatordan "toshib" ko'rinib qolardi.
  • Yopiq holatda mazmun hamon bor. U ko'rinmaydi, lekin ekran o'quvchi o'qiydi va ichidagi havolaga Tab boradi. Bu yerda bu yaxshi: tarkib muhim ma'lumot. Butunlay yashirish kerak bo'lsa — visibility: hidden qo'shing (Transition darsidagi naqsh).
  • Harakat emas, o'lcham o'zgarishi. Bu layout animatsiyasi: har kadrda karta va ostidagi hamma narsa qayta joylashadi. Kichik panellar uchun normal, butun sahifa ro'yxati uchun og'ir (Rendering va samaradorlik).

Tekshirib ko'ring: Nega .ochiluvchi ga oddiy height: 0 → height: 1fr yozib bo'lmaydi?

Javob

fr — faqat grid treklari (grid-template-rows, grid-template-columns) uchun birlik (Grid'ga kirish). height: 1fr — noto'g'ri qiymat, brauzer uni tashlab ketadi. Hiyla aynan shunda: balandlikni to'g'ridan-to'g'ri emas, otaning grid qatori orqali boshqaramiz.

4.3 Yangi yo'l: interpolate-size: allow-keywords

Grid hiylasi ortiqcha div talab qiladi. Chrome 129 dan boshlab to'g'ridan-to'g'ri yo'l bor:

css
:root {
  interpolate-size: allow-keywords;
}

.tarkib {
  height: 0;
  overflow: clip;
  transition: height 0.3s ease-out;
}

.ochiq .tarkib {
  height: auto;
}

interpolate-size: allow-keywords — "auto, min-content, fit-content kabi o'lcham kalit so'zlariga transition qilishga ruxsat". U meros o'tadi — shuning uchun bir marta :root ga yoziladi va butun sahifaga ta'sir qiladi (Meros). Nega odatiy emas? Eski saytlarda height: auto ga yozilgan transition'lar "uxlab yotgan" — ular birdan ishlab ketsa, dizayn buzilishi mumkin. Shuning uchun ruxsatni o'zingiz yoqasiz.

Chrome'da o'lchadik: 0 dan auto (52 piksel) gacha 1 soniyalik linear o'tishning yarmida balandlik aynan 26 piksel edi.

4.4 calc-size(): aniq joyda

Butun sahifaga ruxsat bermasdan, bitta qiymatda "auto ni son sifatida ishlat" deyish ham mumkin:

css
.ochiq .tarkib {
  height: calc-size(auto, size);
}

calc-size(auto, size) — "auto balandlikni hisobla va uni oddiy son sifatida ber". Ikkinchi qism — hisob: size — o'sha balandlikning o'zi. U bilan matematik amal ham mumkin: calc-size(auto, size + 2rem) — mazmun balandligi va yana 2rem. Chrome'da o'lchadik — interpolate-size bilan bir xil: yarim yo'lda 26 piksel.

Brauzer holati: Baseline ma'lumotiga ko'ra interpolate-size ham, calc-size() ham Baseline emas — hozircha faqat Chrome va Edge'da (129 dan). Firefox va Safari'da ular ishlamaydi: interpolate-size noma'lum xususiyat sifatida tashlanadi va balandlik sakrab ochiladi. calc-size() bilan esa ehtiyot bo'ling: butun deklaratsiya tashlanadi va height 0 da qolib ketadi. Shuning uchun zaxira kerak:

css
.ochiq .tarkib {
  height: auto; /* hamma brauzer: sakrab ochiladi */
  height: calc-size(auto, size); /* Chrome: silliq */
}

interpolate-size bunday xavfga ega emas — height: auto o'zi to'g'ri qiymat, faqat transition qo'shiladi yoki qo'shilmaydi. Shuning uchun amalda odatda u ishlatiladi.

5. details ning silliq ochilishi

details (details va summary) — ochiladigan blokning eng to'g'ri HTML'i: klaviatura, ekran o'quvchi, Ctrl + F bilan qidirish — hammasi o'zi ishlaydi. Endi uning ochilishi ham silliq bo'lishi mumkin.

Yopiq details da summary dan keyingi hamma narsa ::details-content pseudo-elementi ichida turadi. Brauzer uni content-visibility: hidden bilan yashiradi. Bu xususiyat "ichini chizma" degani — display: none ga o'xshaydi, lekin u ham diskret. Uni keyingi darsda batafsil ko'ramiz. Demak, silliq ochish uchun uchta narsa:

  1. ::details-content ning balandligi 0 → auto (interpolate-size bilan);
  2. content-visibility — diskret, u yopilishda darhol yashirmasligi uchun allow-discrete;
  3. overflow: clip — balandlik o'sayotganda ichidagi matn toshib chiqmasin.
html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  details {
    max-width: 20rem;
    padding: 0.25rem 0.75rem;
    border: 2px solid var(--rang-asosiy);
    border-radius: 0.5rem;
    background-color: var(--rang-fon);
  }
  details + details { margin-top: 0.5rem; }
  summary {
    padding-block: 0.25rem;
    color: var(--rang-asosiy);
    font-weight: bold;
  }
  details p { margin: 0 0 0.5rem; }
  @media (prefers-reduced-motion: no-preference) {
    details {
      interpolate-size: allow-keywords;
    }
    details::details-content {
      block-size: 0;
      overflow-y: clip;
      transition:
        block-size 0.3s ease-out,
        content-visibility 0.3s allow-discrete;
    }
    details[open]::details-content {
      block-size: auto;
    }
  }
</style>
<details name="savol">
  <summary>Bron qanday qilinadi?</summary>
  <p>Bron sahifasida ism, telefon, sana va vaqtni yozing.</p>
  <p>Biz 15 daqiqa ichida qo'ng'iroq qilamiz.</p>
</details>
<details name="savol">
  <summary>Nechta odam sig'adi?</summary>
  <p>Bitta bronda 20 kishigacha.</p>
</details>

Nimaga qarang: savolni bosing — javob pastga silliq ochiladi. Ikkinchisini bosing — birinchisi yopiladi (bir xil name — details va summary darsidagi eksklyuziv akkordeon) va ikkalasi bir vaqtda silliq harakatlanadi. Chrome'da o'lchadik: 1 soniyali sinovda details 18 pikseldan 86 pikselgacha ochildi, yarim yo'lda 60 piksel atrofida edi; yopilish ham xuddi shunday teskari.

  • interpolate-size bu yerda details ga yozildi — faqat shu blokka ruxsat. Butun saytda ishlatsangiz, :root ga ko'chiring.
  • Harakat bloki ichida — harakatni kamaytirgan foydalanuvchida details odatdagidek darhol ochiladi.
  • Boshqa brauzerlarda: Baseline ma'lumotiga ko'ra ::details-content 2025-yil sentabrdan hamma asosiy brauzerda (yangi Baseline), interpolate-size esa faqat Chrome'da. Firefox va Safari'da details sakrab ochiladi — xuddi CSS'siz holatdagidek.

Akkordeon va tablarni to'liq — summary belgisi, dizayn, klaviatura — Tabs va accordion darsida quramiz.

6. Qo'llab-quvvatlamasa nima bo'ladi

Bu darsdagi hamma narsa qo'shimcha. Tekshiruv ro'yxati:

Imkoniyat Qo'llamaydigan brauzerda
@starting-style Element transition'siz, darhol paydo bo'ladi
display + allow-discrete Element darhol yo'qoladi
interpolate-size Balandlik sakrab o'zgaradi
calc-size() Deklaratsiya tashlanadi — zaxira height: auto shart
grid-template-rows hiylasi Hamma zamonaviy brauzerda ishlaydi

Faqat bitta holatda sahifa buziladi: zaxirasiz calc-size(). Qolganlarida foydalanuvchi animatsiyani ko'rmaydi, xolos — mazmun, tugmalar, klaviatura ishlayveradi.

Imkoniyat bor-yo'qligiga qarab boshqa CSS yozish ham mumkin — @supports (interpolate-size: allow-keywords) { ... }. Uni Brauzer mosligi: @supports darsida o'rganamiz. Bu darsdagi misollarga u kerak emas: ular zaxirasiz ham to'g'ri ishlaydi.

7. Ko'p uchraydigan xatolar

7.1 @starting-style oddiy qoidadan oldin

Bir xil og'irlikdagi pastki qoida boshlang'ich uslubni ham bosib ketadi. Tuzatish: @starting-style ni keyin yozing yoki qoida ichiga joylang.

7.2 display transition ro'yxatida yo'q

opacity bor, display yo'q — yo'qolish darhol. Tuzatish: display 0.3s allow-discrete ni ro'yxatga qo'shing, davomiyligi boshqalar bilan bir xil bo'lsin.

7.3 transition: all bilan allow-discrete

transition: all 0.3s allow-discrete — endi hamma diskret xususiyatlar ham "kechikib" almashadi: masalan, font-family o'tishning yarmigacha eski shriftda qoladi (Chrome'da tekshirdik: transition yaratildi va shrift darhol emas, kechikib almashdi). Tuzatish: xususiyatlarni nomi bilan yozing.

7.4 Zaxirasiz calc-size()

Chrome'da ishlaydi, Safari'da blok ochilmaydi. Tuzatish: oldiga height: auto qatorini yozing.

7.5 Katta ro'yxatda balandlik animatsiyasi

50 ta kartaning har biri hover'da balandligini o'zgartirsa, butun sahifa har kadrda qayta joylashadi — telefonda "tutilib" qoladi. Tuzatish: balandlik animatsiyasini kam va kichik bloklarda ishlating; ko'p takrorlanadigan effektlarga opacity va translate (Rendering va samaradorlik).

8. Mashqlar

1-mashq (oson): Aksiya sahifa bilan birga chiqsin

«Bahor» bosh sahifasidagi aksiya matni (p class="aksiya") sahifa ochilganda 0.4 soniyada xiralikdan chiqsin va 1rem pastdan suzib kelsin. @keyframes ishlatmang. Suzish faqat harakat ruxsat bo'lsa.

Ishora: sahifa yuklanishi ham "birinchi chizilish". Qoida ichidagi @starting-style shakli tartib tuzog'idan xoli.

Yechim
css
.aksiya {
  transition: opacity 0.4s ease-out;

  @starting-style {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .aksiya {
    transition:
      opacity 0.4s ease-out,
      translate 0.4s ease-out;

    @starting-style {
      translate: 0 1rem;
    }
  }
}
  • opacity: 1 va translate: 0 yozilmagan — ular odatiy qiymatlar, transition oxiri shu.
  • Ikkinchi @starting-style birinchisini almashtirmaydi: har biri o'z xususiyatini beradi. Harakat ruxsat bo'lsa, boshlang'ich holat — opacity: 0 va translate: 0 1rem.
  • Eski brauzerda aksiya shunchaki darhol ko'rinadi.

2-mashq (o'rta): Menyu yopilishda "g'oyib" bo'ladi

Stajyor «Bahor» menyusini shunday yozdi. Ochilish silliq, yopilish esa darhol. Sababini toping va tuzating.

css
nav li ul {
  display: none;
  opacity: 0;
  transition: opacity 0.2s ease-out;
}

nav li:hover > ul {
  display: flex;
  opacity: 1;
}

@starting-style {
  nav li:hover > ul {
    opacity: 0;
  }
}

Ishora: ochilishda display o'zi none dan chiqadi, @starting-style yetadi. Yopilishda-chi?

Yechim

Yopilishda display darhol none bo'ladi — u transition ro'yxatida yo'q va allow-discrete siz diskret xususiyat kechikmaydi. Element yo'qolgach opacity o'tishini hech kim ko'rmaydi.

css
nav li ul {
  display: none;
  opacity: 0;
  transition:
    opacity 0.2s ease-out,
    display 0.2s allow-discrete;
}

@starting-style bu yerda to'g'ri joyda — oddiy qoidadan keyin, shuning uchun ochilish ishlagan edi. Yana ikki yaxshilash: :focus-within qo'shing (klaviatura uchun) va display Firefox'da hali o'tmasligini unutmang — u yerda yopilish baribir darhol bo'ladi, bu normal.

3-mashq (qiyin): Hamma brauzerda ochiladigan "Batafsil"

«Bahor» bron sahifasida "Bron qoidalari" bloki. Tugma yo'q — sarlavha ustiga sichqoncha kelganda yoki blok ichiga fokus kirganda matn silliq ochilsin. Talablar:

  1. Firefox va Safari'da ham silliq.
  2. Yopiq matn ko'rinmaydi va Tab unga bormaydi; ochilganda ichidagi havola fokus oladi.
  3. Harakatni kamaytirgan foydalanuvchida — darhol ochiladi.
html
<section class="qoidalar" tabindex="0">
  <h2>Bron qoidalari</h2>
  <div>
    <div>
      <p>Bron 2 soat saqlanadi. Kechiksangiz, qo'ng'iroq qiling.</p>
      <p><a href="#">To'liq qoidalar</a></p>
    </div>
  </div>
</section>

qoidalar — namoyish nomi.

Ishora: 1-band — "Hamma brauzerda" bo'limidagi grid hiylasi. 2-band — Transition darsidagi visibility naqshi: yopilishda oxirida hidden, ochilishda darhol visible. :focus-within bo'limning o'zida tabindex="0" bo'lgani uchun ishlaydi.

Yechim
html
<style>
  body { font-family: system-ui, sans-serif; }
  .qoidalar {
    max-width: 22rem;
    padding: 0.5rem 1rem;
    border: 2px solid #2f6b3a;
    border-radius: 0.5rem;
  }
  .qoidalar h2 { margin: 0; font-size: 1.1rem; }
  .qoidalar > div {
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;
  }
  .qoidalar > div > div { overflow: hidden; }
  .qoidalar:hover > div,
  .qoidalar:focus-within > div {
    grid-template-rows: 1fr;
    visibility: visible;
  }
  @media (prefers-reduced-motion: no-preference) {
    .qoidalar > div {
      transition:
        grid-template-rows 0.3s ease-out,
        visibility 0.3s;
    }
  }
</style>
<section class="qoidalar" tabindex="0">
  <h2>Bron qoidalari</h2>
  <div>
    <div>
      <p>Bron 2 soat saqlanadi. Kechiksangiz, qo'ng'iroq qiling.</p>
      <p><a href="#">To'liq qoidalar</a></p>
    </div>
  </div>
</section>
  • Grid hiylasi — Baseline'da, Firefox va Safari'da ham silliq.
  • visibility yopiq matnni Tab va ekran o'quvchidan yashiradi. Transition'da u yopilishda oxirida hidden bo'ladi — shuning uchun matn yopilayotganda ko'rinib turadi. Ochilishda darhol visible — havola fokus ola boshlaydi.
  • Fokus zanjiri: Tab → bo'limning o'zi (tabindex="0") → :focus-within matnni ochadi → keyingi Tab — havolaga. Havola fokusda bo'lganda ham :focus-within ishlaydi.
  • Haqiqiy loyihada bunday blok uchun details yaxshiroq (details va summary) — sichqonchasiz ham ochiladi. Bu mashq — texnika uchun.

4-mashq: Portfolio qadami — savol-javob silliq ochilsin

Portfolio'dagi "Aloqa" sahifasida savol-javob bor — details[name="savollar"] (Yakuniy loyiha). Ular hozir sakrab ochiladi. Silliq qiling:

  1. Chrome'da javob 0.25 soniyada silliq ochilsin va yopilsin.
  2. Boshqa brauzerlarda hozirgidek ishlasin — hech narsa buzilmasin.
  3. Faqat harakat ruxsat bo'lsa.
  4. Chrome'da ikkita savolni navbat bilan oching: biri yopilib, ikkinchisi ochilayotganda sahifa "sakrayaptimi"?

Ishora: "details ning silliq ochilishi" bo'limi. Qoidalar "6. Afzalliklar va qurilma" bo'limidagi harakat blokiga tushadi. interpolate-size ni faqat savol-javobga bering — butun saytga emas.

Yechim

"6. Afzalliklar va qurilma" bo'limidagi @media (hover: hover) and (prefers-reduced-motion: no-preference) blokiga emas — savol-javob telefonda ham ochiladi. Alohida blok:

css
/* Savol-javob silliq ochiladi — Chrome'da; boshqalarda odatdagidek
   (Kirish va chiqish animatsiyalari darsi) */
@media (prefers-reduced-motion: no-preference) {
  details[name="savollar"] {
    interpolate-size: allow-keywords;
  }

  details[name="savollar"]::details-content {
    block-size: 0;
    overflow-y: clip;
    transition:
      block-size 0.25s ease-out,
      content-visibility 0.25s allow-discrete;
  }

  details[name="savollar"][open]::details-content {
    block-size: auto;
  }
}

Chrome'da tekshirdik:

  • Javob silliq ochiladi va yopiladi. Ikkinchi savol ochilganda birinchisi bir vaqtda yopiladi — ostidagi kontent ikkala o'zgarish yig'indisiga qarab suriladi, sakrash yo'q.
  • details dagi padding va ochiq holatdagi --karta-chegara rangi (Yakuniy loyiha) o'zgarishsiz: rang [open] bilan darhol almashadi, balandlik esa silliq o'sadi.
  • Firefox va Safari'da ::details-content bor, lekin interpolate-size yo'q — block-size: auto darhol qo'llanadi va details odatdagidek ochiladi.

Nega (hover: hover) bloki emas? Bu qoidalar sichqonchaga bog'liq emas: telefonda ham barmoq bilan bosib ochiladi. Faqat harakat sharti yetadi.

9. Real ishda

  • Ochiladigan menyular, toast va bildirishnomalar — @starting-style va allow-discrete bilan JavaScript'dagi "animatsiya tugashini kutib, keyin display: none" kodi keraksiz bo'ladi. Dialog va popover'larga qo'llanishini Top layer darsida ko'ramiz.
  • Akkordeonlar — Radix, Headless UI kabi kutubxonalar balandlikni JavaScript bilan o'lchab animatsiya qilardi. Yangi loyihalarda ::details-content va interpolate-size bu ishni CSS'ga olmoqda (Tabs va accordion).
  • React'da Framer Motion (Motion) kutubxonasining AnimatePresence komponenti aynan "yo'qolish animatsiyasi" muammosini hal qilish uchun yaratilgan (kursda keyin, hozir bilish shart emas). CSS endi uning bir qismini o'zi qiladi.
  • Brauzer mosligi — kasbiy ko'nikma. Yangi imkoniyatni ishlatishdan oldin Baseline holatini tekshirish va zaxira yozish — jamoada kutiladigan odat (Brauzer mosligi).
  • Intervyuda so'raladi: "Nega display: none ga transition ishlamaydi va buni qanday hal qilasiz?", "height: auto ni qanday animatsiya qilasiz?", "@starting-style nima?"

Xulosa

  • display: none dan chiqqan elementda "oldingi" uslub yo'q — @starting-style uni yozadi; u sahifa yuklanganda ham ishlaydi.
  • @starting-style specificity qo'shmaydi — oddiy qoidadan keyin yoki uning ichida yozing.
  • transition-behavior: allow-discrete diskret xususiyatni (display, content-visibility, overlay) transition oxirigacha ushlab turadi.
  • height: auto: hamma brauzerda — grid-template-rows: 0fr → 1fr; Chrome'da — interpolate-size: allow-keywords yoki zaxirali calc-size().
  • details silliq ochiladi: ::details-content + interpolate-size + content-visibility allow-discrete bilan.
  • Hammasi — progressive enhancement: qo'llamaydigan brauzerda animatsiya yo'q, lekin hech narsa buzilmaydi.

Keyingi dars: Rendering pipeline va animatsiya samaradorligi — nega translate va opacity silliq, height va width esa "og'ir" ekanini brauzer ichidan ko'ramiz.

Manbalar

  • MDN: "@starting-style", "transition-behavior", "interpolate-size", "calc-size()", "::details-content" — developer.mozilla.org
  • W3C: "CSS Transitions Level 2" (@starting-style, allow-discrete), "CSS Values and Units Level 5" (calc-size(), interpolate-size) — w3.org/TR
  • Chrome for Developers: "Animate to height: auto; (and other intrinsic sizing keywords) in CSS" — developer.chrome.com/blog
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS @starting-style: kirish va chiqish animatsiyalari, display: none va height: auto — IlmHamroh