IlmHamroh
JavaScript Full-stack/6-qism. CSS: harakat, zamonaviy CSS va dizayn11/57-dars18 daqiqa
Mundarija (32)

CSS @property: turlangan custom property'lar va gradient animatsiyasi

Qisqacha: Oddiy CSS o'zgaruvchisi brauzer uchun shunchaki matn, shuning uchun uni silliq animatsiya qilib bo'lmaydi — qiymat bir zumda sakraydi. @property --x { syntax: '<angle>'; inherits: false; initial-value: 0deg; } o'zgaruvchiga tur beradi. Endi brauzer uning burchak ekanini biladi va oraliq qiymatlarni o'zi hisoblaydi. Shu tufayli gradient, konus chegara va hatto sanoqni animatsiya qilish mumkin. Noto'g'ri turdagi qiymat berilsa, brauzer initial-value ni ishlatadi.

Bu darsda

  • Nega oddiy o'zgaruvchi animatsiyada "sakrashini" tushuntira olasiz.
  • @property ning uch qismini — syntax, inherits, initial-value — yoza olasiz va qaysi biri majburiy ekanini bilasiz.
  • Gradient rangini, konus chegara burchagini va foiz sanog'ini silliq animatsiya qilasiz.
  • inherits: false nima berishini va var() zaxirasi nega endi ishlamasligini bilasiz.
  • CSS.registerProperty va Houdini nima ekanini qisqa tushuntira olasiz.

Oldin bilishingiz kerak: CSS o'zgaruvchilari 2, @keyframes va animation, Transition, Gradientlar.

1. Nega bu kerak?

Native CSS nesting darsida kodni tartibli yozishni o'rgandik. Endi o'zgaruvchilarga qaytamiz — ularning bitta katta cheklovi bor edi.

Jasur aka «Bahor» menyusidagi yangi taom kartasi atrofida aylanib turuvchi rangli chegara xohlaydi. Chegara ranglari aylana bo'ylab yursin — xuddi choyxona peshtaxtasidagi yonib-o'chib turuvchi chiroqlar kabi. Gradientlar darsidan bilamiz: conic-gradient(from 0deg, ...) konus gradient chizadi, from esa uning boshlanish burchagi. Burchakni o'zgaruvchiga qo'yib, uni @keyframes bilan 0 dan 360 gradusgacha o'zgartiramiz.

Mantiqan to'g'ri. Lekin brauzerda ishlamaydi:

html
<style>
  @property --burchak {
    syntax: '<angle>';
    inherits: false;
    initial-value: 0deg;
  }
  @keyframes aylan {
    to { --burchak: 360deg; }
  }
  @keyframes aylan-oddiy {
    to { --oddiy: 180deg; }
  }
  .taom-karta {
    padding: 12px 16px;
    margin-block-end: 12px;
    border: 4px solid transparent;
    border-radius: 12px;
    animation: aylan 3s linear infinite;
  }
  .oddiy {
    --oddiy: 0deg;
    animation-name: aylan-oddiy;
    background:
      linear-gradient(#fffaf0, #fffaf0) padding-box,
      conic-gradient(from var(--oddiy),
        #2f6b3a, #b4461a, #2f6b3a) border-box;
  }
  .turli {
    background:
      linear-gradient(#fffaf0, #fffaf0) padding-box,
      conic-gradient(from var(--burchak),
        #2f6b3a, #b4461a, #2f6b3a) border-box;
  }
</style>
<article class="taom-karta oddiy">
  <h3>❌ Tandir go'sht</h3>
  <p>Oddiy o'zgaruvchi: chegara sakraydi</p>
</article>
<article class="taom-karta turli">
  <h3>✅ Tandir go'sht</h3>
  <p>@property bilan: chegara silliq aylanadi</p>
</article>

Nimaga qarang: pastki kartaning yashil-qizg'ish chegarasi to'xtovsiz, silliq aylanadi. Yuqoridagi karta esa har 1,5 soniyada "sakraydi": ranglar birdan yarim aylanaga burilib qoladi, oraliq holat yo'q. Ikkala animatsiya ham burchakni o'zgartiradi (yuqorisida — yarim aylanagacha, chunki 0 va 360 gradusda rasm bir xil). Farq bitta: pastkisining o'zgaruvchisi @property bilan ro'yxatdan o'tgan.

Maslahat: Skrinshot yoki bitta kadrda harakat ko'rinmaydi — natijani sahifada oching va 5–6 soniya kuzating. Kompyuteringizda "harakatni kamaytirish" yoqilgan bo'lsa ham bu blok aylanadi: bu yerda maqsad — farqni ko'rsatish. Haqiqiy saytda esa harakat albatta o'chiriladi (pastda, «Harakatni kamaytirish» bo'limida).

2. Nega oddiy o'zgaruvchi sakraydi?

2.1 Brauzer uchun o'zgaruvchi — matn bo'lagi

CSS o'zgaruvchilari 2 darsida muhim fakt bor edi: brauzer --oddiy: 360deg ni o'qiganda uning ichiga qaramaydi. Uning uchun bu "360deg" degan belgilar ketma-ketligi, xolos. Burchakmi, rangmi, ismmi — bilmaydi. Tekshirish faqat var() ishlatilgan joyda bo'ladi.

Animatsiya uchun esa brauzer oraliq qiymatni hisoblashi kerak. 0deg va 360deg orasi — 180deg. Lekin "salom" va "xayr" orasida nima bor? Turini bilmagani uchun brauzer oraliqni umuman hisoblamaydi: animatsiya yarmigacha eski qiymat, yarmidan keyin yangisi. Bunday o'zgarish diskret (discrete) deyiladi — pog'onali, silliq emas.

@starting-style darsida display ham shunday diskret o'zgarishini ko'rgan edik: "ko'rinadi" va "ko'rinmaydi" orasida yarim holat yo'q.

2.2 @property — o'zgaruvchining pasporti

@property — o'zgaruvchini brauzerga "ro'yxatdan o'tkazadigan" @-qoida. U brauzerga uch narsani aytadi: qiymat qaysi turda, meros o'tadimi va boshlang'ich qiymati qanday. Xuddi yangi xodimni ishga olganda to'ldiriladigan anketa kabi: kasbi, qaysi bo'limga tegishli, birinchi kuni nima qiladi.

css
@property --burchak {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

Endi brauzer biladi: --burchak — har doim burchak. 0deg va 360deg orasidagi har kadrni u o'zi hisoblaydi — xuddi transform: rotate() dagi kabi. Bunday o'zgaruvchi ro'yxatdan o'tgan (registered) custom property deb ataladi. Ba'zan "turlangan (typed) o'zgaruvchi" ham deyishadi.

Animatsiyaning har kadrida brauzer bitta savol beradi:

flowchart TD
  A["O'zgaruvchi 0deg → 360deg"] --> B{"Turi ma'lummi?<br/>(@property bormi)"}
  B -->|Yo'q| C["Yarim yo'lgacha 0deg,<br/>keyin birdan 360deg"]
  B -->|Ha| D["Har kadrda oraliq:<br/>90deg, 180deg, 270deg..."]
  C --> E["Sakraydi"]
  D --> F["Silliq aylanadi"]

Nimaga qarang: ikkala yo'lda ham kod bir xil @keyframes. Farqni faqat "turi ma'lummi?" degan savolning javobi beradi.

Chrome'da o'lchadik: ro'yxatdan o'tmagan --oddiy 1 soniyalik transition boshlanishi bilan darhol oxirgi qiymatga o'tdi. Ro'yxatdan o'tgan --burchak esa yarim soniyada 90.018deg ni ko'rsatdi — ya'ni yo'lning yarmida edi.

Tekshirib ko'ring: Nega brauzer oddiy o'zgaruvchini animatsiya qilishdan "qo'rqadi"?

Javob

Chunki u o'zgaruvchi ichida nima borligini bilmaydi — burchakmi, rangmi yoki shunchaki so'zmi. So'zlar orasida oraliq qiymat yo'q. Shuning uchun brauzer xavfsiz yo'lni tanlaydi: qiymatni yarim yo'lda birdan almashtiradi. @property turini aytgach, oraliqni hisoblash mumkin bo'ladi.

3. @property ning uch qismi

3.1 syntax — qiymat turi

syntax qo'shtirnoq ichida yoziladi. < va > belgilari orasidagi so'z — turning nomi. Eng kerakli turlar:

syntax Qanday qiymat Misol
'<length>' Uzunlik 12px, 1.5rem
'<percentage>' Foiz 75%
'<number>' Son 0.5, 3
'<integer>' Butun son 42
'<angle>' Burchak 45deg, 0.5turn
'<color>' Rang #2f6b3a, oklch(...)
'<time>' Vaqt 300ms

Yana bir nechta kamroq ishlatiladigani bor: '<length-percentage>' (uzunlik yoki foiz), '<image>' (rasm yoki gradient — lekin u animatsiya bo'lmaydi), '<transform-function>'. Birlashtirish ham mumkin:

  • '<color> | <length>' — rang yoki uzunlik.
  • '<length>+' — bo'sh joy bilan ajratilgan uzunliklar ro'yxati (1px 2px).
  • 'osh | manti' — faqat shu ikki so'zdan biri.
  • '*' — istalgan qiymat. Bu oddiy o'zgaruvchi bilan bir xil: tur yo'q, animatsiya ham yo'q.

Diqqat: Qo'shtirnoq majburiy. syntax: <color>; deb yozsangiz, brauzer butun @property qoidasini jimgina tashlab ketadi — Chrome'da tekshirdik: brauzer bunday qoidani umuman saqlamadi. Xato xabari ham chiqmaydi.

3.2 inherits — meros o'tadimi

inherits: true — o'zgaruvchi oddiy o'zgaruvchi kabi bolalarga meros o'tadi. inherits: false — faqat shu elementning o'zida yashaydi. Bolalari uni initial-value qiymatida ko'radi.

html
<style>
  @property --chiziq {
    syntax: '<length>';
    inherits: false;
    initial-value: 2px;
  }
  .taom-karta {
    --chiziq: 8px;
    --oddiy: 8px;
    padding: 12px;
    background-color: #fffaf0;
  }
  .taom-karta p {
    padding-inline-start: 8px;
  }
  .birinchi {
    border-inline-start: var(--chiziq) solid #2f6b3a;
  }
  .ikkinchi {
    border-inline-start: var(--oddiy) solid #b4461a;
  }
</style>
<article class="taom-karta">
  <p class="birinchi">Osh — --chiziq bolaga yetmadi: 2px</p>
  <p class="ikkinchi">Lag'mon — oddiy --oddiy meros o'tdi: 8px</p>
</article>

Nimaga qarang: ikkala o'zgaruvchi ham kartaning o'ziga 8px deb yozilgan, paragraflar esa uning bolalari. Yashil chiziq ingichka — 2px: inherits: false sabab paragraf --chiziq ni meros olmadi va initial-value ni ishlatdi. Qizg'ish chiziq qalin — 8px: oddiy o'zgaruvchi odatdagidek meros o'tdi.

Nega false kerak? Tezlik uchun. O'zgaruvchi har kadrda o'zgarganda (animatsiyada sekundiga 60 marta), brauzer uni meros oladigan hamma ichki elementlar stilini qayta hisoblashi kerak. Kartada 20 ta ichki element bo'lsa — 20 barobar ish. inherits: false da faqat bitta element qayta hisoblanadi. Animatsiya qilinadigan o'zgaruvchilarni deyarli har doim inherits: false qiling (Rendering pipeline darsida bu "style" bosqichi edi).

true qachon kerak? Mavzu ranglari kabi butun sahifaga tarqaladigan o'zgaruvchilar uchun — --rang-asosiy ni :root ga yozib, hamma joyda ishlatasiz.

3.3 initial-value — boshlang'ich qiymat

O'zgaruvchi hech qayerda berilmagan bo'lsa (yoki noto'g'ri berilsa), brauzer shu qiymatni ishlatadi. Ikki qoida bor:

  1. syntax: '*' dan boshqa har qanday turda majburiy. Yozilmasa, butun qoida tashlanadi.
  2. Qiymat mustaqil bo'lishi kerak: boshqa narsaga qaramasdan hisoblansin. 0deg, 2px, #2f6b3a, transparent — to'g'ri. 1em (shriftga bog'liq), 2rem (html shriftiga bog'liq) va var(--rang-asosiy) — noto'g'ri. Chrome'da tekshirdik: initial-value: 1em li qoida butunlay e'tiborsiz qoldi.

inherits ham majburiy — uni tushirib qoldirsangiz ham qoida tashlanadi (tekshirdik). Qisqasi: uchala qator doim yozilsin.

Tekshirib ko'ring: @property --bosh { syntax: '<length>'; inherits: false; initial-value: 1rem; } ishlaydimi?

Javob

Yo'q. 1rem — html ning shrift o'lchamiga bog'liq, u esa CSS bilan o'zgarishi mumkin. initial-value esa mustaqil bo'lishi shart. Brauzer butun qoidani tashlab ketadi va --bosh oddiy, turi yo'q o'zgaruvchi bo'lib qoladi. To'g'risi: initial-value: 16px.

4. Tur tekshiruvi: noto'g'ri qiymat rad etiladi

CSS o'zgaruvchilari 2 darsida --rang-urgu: 20px kabi xatoni ko'rgan edik va "@property bilan brauzer noto'g'ri qiymatni rad qiladi" degan edik. Mana u:

html
<style>
  @property --rang-urgu {
    syntax: '<color>';
    inherits: true;
    initial-value: #b4461a;
  }
  .narx {
    font-size: 24px;
    font-weight: bold;
  }
  .bir {
    --rang-urgu: 20px;
    color: var(--rang-urgu);
  }
  .ikki {
    --x: 20px;
    color: var(--x);
  }
</style>
<p class="narx bir">Osh — 35 000 so'm</p>
<p class="narx ikki">Manti — 30 000 so'm</p>

Nimaga qarang: osh narxi qizg'ish chiqdi, manti narxi esa qora. Ikkalasida ham o'zgaruvchiga rang o'rniga 20px yozildi.

  • --rang-urgu ro'yxatdan o'tgan. Brauzer 20px rang emasligini ko'rdi va uni initial-value — #b4461a bilan almashtirdi. Sahifa "buzilmadi", brend rangida qoldi.
  • --x oddiy o'zgaruvchi. color: 20px hisoblash vaqtida yaroqsiz bo'ldi va color otasidan meros oldi — qora.

Bitta nozik joy bor. Bir blok ichida avval to'g'ri, keyin noto'g'ri qiymat yozsangiz: --rang-urgu: green; --rang-urgu: 20px; — natija yashil emas. Chrome'da tekshirdik: brauzer oxirgi deklaratsiyani oladi, u noto'g'ri turda bo'lgani uchun initial-value ishlaydi. Oldingi to'g'ri qiymat "zaxira" bo'lmaydi — CSS'ning birinchi darsidagi oddiy xususiyatlardan farqi shu.

5. Uchta amaliy animatsiya

5.1 Gradient rangi — hover'da silliq

Transition darsida background-color ni silliq o'zgartirgan edik. Gradientni esa to'g'ridan-to'g'ri transition qilib bo'lmaydi — background-image diskret o'zgaradi. Hiyla: gradient ichidagi rangni o'zgaruvchiga chiqaramiz va o'zgaruvchini ro'yxatdan o'tkazamiz.

html
<style>
  @property --_rang {
    syntax: '<color>';
    inherits: false;
    initial-value: #2f6b3a;
  }
  .bron-havola {
    display: inline-block;
    padding: 12px 24px;
    border-radius: 8px;
    color: #fffaf0;
    font: bold 18px system-ui, sans-serif;
    text-decoration: none;
    background: linear-gradient(135deg, var(--_rang), #1a5d1a);
    transition: --_rang 0.4s ease-out;
  }
  .bron-havola:hover,
  .bron-havola:focus-visible {
    --_rang: #b4461a;
  }
</style>
<a class="bron-havola" href="#bron">Stolni band qilish</a>

Nimaga qarang: tugma ustiga sichqonchani olib keling yoki Tab bilan fokus bering — gradientning chap tomoni yashildan qizg'ishga yarim soniyada, asta-sekin o'tadi. transition da xususiyat nomi o'rniga o'zgaruvchi nomi yozildi: --_rang. Nom boshidagi _ — "bu faqat shu komponent ichidagi o'zgaruvchi" degan kelishuv (CSS o'zgaruvchilari 2).

5.2 Konus chegara — cheksiz aylanish

Darsning boshidagi aylanuvchi chegara endi tushunarli. Qayta ko'rib chiqamiz:

  • border: 4px solid transparent — chegara joyi bor, lekin rangsiz.
  • Ikki qatlamli fon (Fonlar): ustki qatlam qaymoq rang, faqat padding-box gacha. Pastkisi konus gradient, border-box gacha — u faqat shaffof chegara ortidan ko'rinadi.
  • @keyframes aylan { to { --burchak: 360deg; } } — burchak 0 dan 360 gacha. from yozilmagan: boshlanish qiymati initial-value dan olinadi.

Bitta o'zgaruvchi ko'p joyda ishlatilishi mumkin. Masalan, xuddi shu --burchak bilan ikkinchi gradient teskari aylanishi mumkin: from calc(var(--burchak) * -1).

5.3 Sanoq — raqam ham o'zgaruvchi

<integer> turi eng qiziq imkoniyatni ochadi: raqamni "sanab" ko'rsatish. CSS hisoblagichlari sonni matnga aylantira oladi, @property esa sonni animatsiya qiladi.

html
<style>
  @property --foiz {
    syntax: '<integer>';
    inherits: false;
    initial-value: 0;
  }
  @keyframes toldir {
    to { --foiz: 75; }
  }
  .band {
    display: grid;
    place-items: center;
    width: 160px;
    aspect-ratio: 1;
    border-radius: 50%;
    background: conic-gradient(
      #2f6b3a calc(var(--foiz) * 1%), #e8f1ec 0);
    animation: toldir 2s ease-out forwards;
    counter-reset: son var(--foiz);
  }
  .band::after {
    content: counter(son) "%";
    display: grid;
    place-items: center;
    width: 75%;
    aspect-ratio: 1;
    border-radius: 50%;
    background-color: #fffaf0;
    font: bold 32px system-ui, sans-serif;
    color: #1f2a24;
  }
</style>
<p>Bugungi stollar band bo'lishi:</p>
<div class="band" role="img" aria-label="75 foiz"></div>

Nimaga qarang: sahifa ochilganda halqa 0 dan boshlab to'ladi, o'rtadagi raqam esa 0, 1, 2... deb 75 gacha sanaydi. Ikkalasini bitta --foiz boshqaradi: calc(var(--foiz) * 1%) — halqa uchun, counter-reset — raqam uchun. forwards animatsiya tugagach 75 da to'xtatadi (@keyframes).

Chrome'da o'lchadik: animatsiya o'rtasida --foiz butun son — masalan 31, hech qachon 31.4 emas. <integer> turi har kadrni yaxlitlaydi. role="img" va aria-label — ekran o'quvchi uchun: ::after dagi o'zgarib turuvchi raqamni u o'qimasligi mumkin.

Tekshirib ko'ring: Yuqoridagi misolda syntax: '<integer>' o'rniga '*' yozilsa nima bo'ladi?

Javob

'*' — "istalgan qiymat", ya'ni tur yo'q. Brauzer yana oraliqni hisoblamaydi: halqa va raqam animatsiya yarmida birdan 0 dan 75 ga sakraydi. Silliq sanoq uchun tur aniq bo'lishi kerak.

6. var() zaxirasi va ro'yxatdan o'tgan o'zgaruvchi

CSS o'zgaruvchilari 2 darsidan eslang: var(--karta-chegara, var(--rang-chegara)) — o'zgaruvchi yo'q bo'lsa, zaxira ishlaydi.

Ro'yxatdan o'tgan o'zgaruvchi esa hech qachon "yo'q" bo'lmaydi: hech qayerda yozilmasa ham uning initial-value si bor. Demak, zaxira endi hech qachon ishlamaydi. Bu portfolio'da muhim — «Portfolio qadami» mashqida aynan shu holatga duch kelamiz.

Qoida: o'zgaruvchini ro'yxatdan o'tkazsangiz, uni ishlatgan joylardagi zaxiralarni tekshiring. Kerakli qiymatni zaxira bilan emas, elementning o'ziga yozib bering.

7. JavaScript'dan: CSS.registerProperty

@property ning JavaScript'dagi egizagi bor. JavaScript'ni 08-qismdan o'rganasiz — hozir faqat ko'rinishini bilib qo'ying, yodlash shart emas:

js
CSS.registerProperty({
  name: "--burchak",
  syntax: "<angle>",
  inherits: false,
  initialValue: "0deg",
});

Ma'nosi @property bilan bir xil, faqat nomlar JavaScript uslubida: initial-value → initialValue. Bitta farq: CSS'dagi xato jim tashlanadi, JavaScript esa xatoni baland aytadi. initialValue yozilmasa, Chrome shunday xato beradi:

text
SyntaxError: Failed to execute 'registerProperty' on 'CSS': An initial value must be provided if the syntax is not '*'

Tarjimasi: "CSS ning registerProperty metodi bajarilmadi: agar syntax '*' bo'lmasa, boshlang'ich qiymat berilishi shart."

JavaScript varianti asosan kutubxonalar ichida kerak. Saytingizda @property yetarli va qulayroq.

7.1 Houdini — @property ning "oilasi"

CSS Houdini — dasturchiga brauzerning CSS dvigateliga kirish imkonini beradigan API'lar to'plami. @property — uning eng muvaffaqiyatli qismi (rasmiy nomi — Properties and Values API). Boshqa a'zolari hali keng tarqalmagan: masalan, JavaScript bilan fon chizadigan paint() Baseline ma'lumotiga ko'ra faqat Chrome va Edge'da bor. Eski maqolalarda "Houdini" so'zini ko'rsangiz, bilingki: bugun undan amalda asosan @property ishlatiladi.

8. Brauzer mosligi va harakatni kamaytirish

8.1 Baseline holati

Baseline ma'lumotiga ko'ra @property va CSS.registerProperty — Baseline 2024 (yangi): 2024-yil iyulidan hamma asosiy brauzerda bor. Oxirgi bo'lib Firefox 128 qo'shdi; Chrome 85 dan, Safari 16.4 dan beri qo'llaydi. Yangi — demak, ba'zi foydalanuvchilarning eski brauzerida hali ishlamaydi.

Eski brauzerda nima bo'ladi? @property qoidasi tashlanadi, o'zgaruvchi oddiy o'zgaruvchi bo'lib ishlayveradi. Natija:

  • Hover'dagi gradient silliq emas, darhol almashadi — lekin almashadi.
  • Aylanuvchi chegara sakrab-sakrab aylanadi.
  • Sanoq 0 dan birdan 75 ga o'tadi.

Hech narsa buzilmaydi, faqat silliqlik yo'qoladi. Bu — Brauzer mosligi darsidagi progressive enhancement: asosiy ma'no hamma joyda, bezak — yangi brauzerlarda.

8.2 Harakatni kamaytirish

prefers-reduced-motion darsidagi qoida bu yerda ham amal qiladi. Cheksiz aylanuvchi chegara — aynan bosh aylantirishi mumkin bo'lgan harakat. Uni faqat foydalanuvchi qarshi bo'lmasa yoqamiz:

css
@media (prefers-reduced-motion: no-preference) {
  .taom-karta.yangi {
    animation: aylan 3s linear infinite;
  }
}

Harakatsiz holatda chegara shunchaki qotib turadi — "yangi" belgisi baribir ko'rinadi. Hover'dagi 0,4 soniyalik rang o'zgarishi esa kichik va foydalanuvchining o'z harakatiga javob — uni qoldirish mumkin.

9. Ko'p uchraydigan xatolar

9.1 Qoida jim tashlandi

Belgilari: animatsiya yana sakraydi, go'yo @property yo'qdek. Sabablari — uch qismdan birida:

  • syntax qo'shtirnoqsiz (syntax: <angle>;);
  • inherits yozilmagan;
  • initial-value yozilmagan yoki mustaqil emas (1em, 2rem, var(...)).

Qanday tekshiriladi: DevTools → Elements → Styles. Ro'yxatdan o'tgan o'zgaruvchi ustiga sichqonchani olib kelsangiz, Chrome uning @property qoidasini ko'rsatadi. Ko'rsatmasa — qoida tashlangan.

9.2 Zaxira ishlamay qoldi

var(--karta-chegara, var(--rang-chegara)) — ro'yxatdan o'tkazgandan keyin karta chegarasi yo'qoldi. Sabab: zaxira endi hech qachon ishlamaydi, o'zgaruvchi initial-value ni — masalan, transparent ni — oladi. Tuzatish: qiymatni elementning o'ziga yozing: --karta-chegara: var(--rang-chegara);.

9.3 O'zgaruvchi otada, ishlatilishi bolada

.taom-karta:hover { --_rang: #b4461a; } yozildi, --_rang esa karta ichidagi tugmada ishlatilgan va inherits: false. Tugma rangi o'zgarmaydi — o'zgaruvchi bolaga yetib bormaydi. Tuzatish: yoki o'zgaruvchini tugmaning o'ziga yozing (.taom-karta:hover .bron-havola { ... }), yoki inherits: true qiling — lekin tezlikni unutmang.

10. Mashqlar

Mashqlarni kurs/mashqlar/06/ papkasida bajaring: har mashqqa alohida papka, ichida index.html va asosiy.css.

1-mashq (oson): tur ber

Quyidagi o'zgaruvchilar uchun @property yozing:

  1. --soya-kengligi — uzunlik, meros o'tmaydi, boshlang'ichi 0px.
  2. --rang-asosiy — rang, meros o'tadi, boshlang'ichi #2f6b3a.
  3. --shaffoflik — son, meros o'tmaydi, boshlang'ichi 1.

Ishora: turlar jadvali «syntax — qiymat turi» bo'limida. Uchala qator ham majburiy.

Yechim
css
@property --soya-kengligi {
  syntax: '<length>';
  inherits: false;
  initial-value: 0px;
}

@property --rang-asosiy {
  syntax: '<color>';
  inherits: true;
  initial-value: #2f6b3a;
}

@property --shaffoflik {
  syntax: '<number>';
  inherits: false;
  initial-value: 1;
}

0px da birlik yozildi — <length> turida 0 ham qabul qilinadi, lekin birlik bilan niyat aniqroq. --rang-asosiy — mavzu rangi, butun sahifaga tarqalishi kerak, shuning uchun inherits: true.

2-mashq (o'rta): «Bahor» aksiya belgisi

«Bahor»ning aksiya matni (class="aksiya") fonida chapdan o'ngga siljib turuvchi yorug' chiziq bo'lsin. Fon: linear-gradient(90deg, #b4461a, #d0643a var(--nur), #b4461a). --nur 0% dan 100% gacha 2 soniyada o'zgarsin, cheksiz takrorlansin. Harakat faqat foydalanuvchi qarshi bo'lmasa ishlasin.

Ishora: --nur — foiz turi ('<percentage>'). @keyframes da from va to ikkalasini yozing. Harakatni cheklash — @media (prefers-reduced-motion: no-preference).

Yechim
html
<style>
  @property --nur {
    syntax: '<percentage>';
    inherits: false;
    initial-value: 50%;
  }
  @keyframes nur-yur {
    from { --nur: 0%; }
    to { --nur: 100%; }
  }
  .aksiya {
    padding: 12px 16px;
    border-radius: 8px;
    color: #fffaf0;
    font: bold 20px system-ui, sans-serif;
    text-align: center;
    background: linear-gradient(90deg,
      #b4461a, #d0643a var(--nur), #b4461a);
  }
  @media (prefers-reduced-motion: no-preference) {
    .aksiya {
      animation: nur-yur 2s linear infinite;
    }
  }
</style>
<p class="aksiya">Aksiya: ikkinchi choynak — bepul!</p>

initial-value: 50% — harakat o'chirilgan bo'lsa yorug' joy o'rtada qotib turadi, belgi chiroyli ko'rinadi. Qaymoq rang matn qizg'ish fonda: #fffaf0 va #b4461a kontrasti 5.3:1 (hisobladik). Eng och joyi — #d0643a — kontrastni 3.6:1 ga tushiradi. Shuning uchun matn qalin va 20px: WCAG katta matn uchun 3:1 ga ruxsat beradi.

3-mashq (qiyin): ikki qiymat — bitta o'zgaruvchi

Taom reytingi: --baho (butun son, 0 dan 5 gacha) bitta o'zgaruvchi bo'lsin. Undan ikki narsa chizilsin:

  1. Chiziq: kengligi calc(var(--baho) * 20%), yashil.
  2. Yozuv: "4 / 5" — raqam hisoblagich bilan.

Sahifa ochilganda baho 0 dan 4 gacha 1,5 soniyada "o'ssin". Harakat o'chirilgan bo'lsa, baho darhol 4 bo'lsin.

Ishora: «Sanoq — raqam ham o'zgaruvchi» bo'limidagi usul. Harakatsiz holatda ham 4 ko'rinishi uchun --baho: 4 ni elementga yozing, animatsiya esa from { --baho: 0; } bilan boshlansin.

Yechim
html
<style>
  @property --baho {
    syntax: '<integer>';
    inherits: true;
    initial-value: 0;
  }
  @keyframes os {
    from { --baho: 0; }
  }
  .reyting {
    --baho: 4;
    counter-reset: baho var(--baho);
    font: 18px system-ui, sans-serif;
  }
  .reyting::after {
    content: counter(baho) " / 5";
    font-weight: bold;
  }
  .chiziq {
    height: 12px;
    width: calc(var(--baho) * 20%);
    border-radius: 6px;
    background-color: #2f6b3a;
  }
  @media (prefers-reduced-motion: no-preference) {
    .reyting {
      animation: os 1.5s ease-out;
    }
  }
</style>
<div class="reyting">
  <p>Osh bahosi:</p>
  <div class="chiziq"></div>
</div>

Ikki nozik joy:

  • inherits: true — bu yerda kerak: --baho ota elementda animatsiya qilinadi, ichki .chiziq esa uni ishlatadi. Ikkitagina element — tezlik muammo emas.
  • @keyframes da faqat from bor. to yozilmasa, animatsiya elementning o'z qiymatiga — 4 ga boradi. Tugagach ham 4 da qoladi: forwards shart emas.

4-mashq: Portfolio qadami — silliq karta chegarasi

Portfolio'ning asosiy.css ida kartalar chegarasi shunday yozilgan (Yakuniy loyiha):

css
.loyihalar > article,
details[name="savollar"],
fieldset {
  border: 1px solid var(--karta-chegara, var(--rang-chegara));
  ...
}

details[name="savollar"][open] {
  --karta-chegara: var(--rang-asosiy);
  ...
}

Vazifa:

  1. --karta-chegara ni rang turi bilan ro'yxatdan o'tkazing (inherits: false).
  2. Savol-javob ochilganda chegara rangi 0,3 soniyada silliq o'zgarsin.
  3. Loyiha kartasi ustiga sichqoncha kelganda ham chegara brend rangiga silliq o'tsin — faqat sichqonchali qurilmada.
  4. Harakatni kamaytirish yoqilgan bo'lsa, rang o'zgaradi, lekin silliqliksiz.
  5. Aloqa sahifasida savolni ochib, loyihalar sahifasida kartaga sichqonchani olib kelib tekshiring. So'ng npm run check.

Ishora: «var() zaxirasi va ro'yxatdan o'tgan o'zgaruvchi» bo'limini qayta o'qing — zaxira endi ishlamaydi. Sichqonchali qurilma sharti — @media (hover: hover) (Mobil tuzoqlar).

Yechim

asosiy.css ning «O'zgaruvchilar va shrift» qismiga, :root dan keyin:

css
/* Karta chegarasi — silliq o'zgarishi uchun tur beramiz
   (@property darsi) */
@property --karta-chegara {
  syntax: '<color>';
  inherits: false;
  initial-value: transparent;
}

Kartalar qoidasida zaxirali var() o'rniga qiymat elementning o'ziga yoziladi:

css
.loyihalar > article,
details[name="savollar"],
fieldset {
  --karta-chegara: var(--rang-chegara);
  border: 1px solid var(--karta-chegara);
  border-radius: 0.5rem;
}

@media (hover: hover) {
  .loyihalar > article:hover {
    --karta-chegara: var(--rang-asosiy);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .loyihalar > article,
  details[name="savollar"] {
    transition: --karta-chegara 0.3s ease-out;
  }
}

details[name="savollar"][open] qoidasi o'zgarmaydi — u allaqachon --karta-chegara ni almashtiradi. Uning og'irligi (0,2,1) umumiy qoidanikidan (0,1,1) katta, shuning uchun ochilganda yutadi (Specificity).

Nega zaxirani olib tashladik? initial-value: transparent bor ekan, var(--karta-chegara, ...) zaxirasi hech qachon ishlamaydi. Eski kodni qoldirsangiz, uchala komponentning chegarasi ko'rinmay qoladi — sinab ko'ring, xatoni o'z ko'zingiz bilan ko'rasiz.

Chrome'da o'lchadik: savol ochilgach, --karta-chegara 50 millisekund oralig'ida och yashildan to'q yashilga bosqichma-bosqich o'tdi va 0,3 soniyada --rang-asosiy ga yetdi. fieldset ga transition berilmadi — u hech qachon rang almashtirmaydi.

11. Real ishda

  • Gradient tugmalar va chegaralar. Landing sahifalardagi "yonib turuvchi" tugma va kartalarning ko'pi — @property + konus gradient.
  • Dizayn tizimlari. Katta loyihalarda mavzu o'zgaruvchilari tur bilan ro'yxatdan o'tkaziladi: noto'g'ri qiymat butun sahifani buzmaydi, initial-value ga qaytadi. Dizayn tokenlari darsida bunga qaytamiz.
  • Raqamli ko'rsatkichlar. Statistika bloklaridagi "0 dan 12 000 gacha sanaydigan" raqamlar — <integer> va hisoblagich bilan, JavaScript'siz.
  • Intervyuda so'raladi: "CSS o'zgaruvchisini nega transition qilib bo'lmaydi va buni qanday tuzatish mumkin?" Javob: brauzer turni bilmaydi → @property bilan tur beriladi.

Xulosa

  • Oddiy CSS o'zgaruvchisi brauzer uchun matn — u animatsiyada diskret, yarim yo'lda sakraydi.
  • @property uch qism talab qiladi: qo'shtirnoqli syntax, inherits, mustaqil initial-value. Bittasi xato bo'lsa, qoida jim tashlanadi.
  • Ro'yxatdan o'tgan o'zgaruvchi gradient rangini, burchakni, foizni va butun sonni silliq animatsiya qiladi.
  • Noto'g'ri turdagi qiymat initial-value bilan almashadi; var() zaxirasi endi ishlamaydi.
  • Animatsiya qilinadigan o'zgaruvchi — inherits: false: brauzer faqat bitta elementni qayta hisoblaydi.
  • Baseline 2024 (yangi): eski brauzerda animatsiya silliqligini yo'qotadi, sahifa buzilmaydi.

Keyingi dars: Skroll xulqi va scroll-snap — silliq skroll, anchor ostidagi bo'shliq va JavaScript'siz "magnitli" galereya yasashni o'rganamiz.

Manbalar

  • MDN: "@property", "CSS.registerProperty()", "CSS Properties and Values API" — developer.mozilla.org
  • W3C: "CSS Properties and Values API Level 1" — w3.org/TR/css-properties-values-api-1
  • web-features (Baseline ma'lumotlari): "registered-custom-properties", "paint" — github.com/web-platform-dx/web-features
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS @property: turlangan custom property'lar va gradient animatsiyasi — IlmHamroh