IlmHamroh
JavaScript Full-stack/9-qism. JavaScript brauzerda va debugging6/29-dars20 daqiqa
Mundarija (35)

JavaScript'da classList va stillar: class, style, CSS o'zgaruvchilari va getComputedStyle

Qisqacha: Ko'rinishni JavaScript'dan o'zgartirishning asosiy yo'li — class almashtirish: element.classList.add("yangi"), remove, toggle, replace, contains. Bunda JavaScript faqat holatni belgilaydi, ranglar va o'lchamlar CSS faylda qoladi. Inline stil (element.style.color) va CSS o'zgaruvchisi (style.setProperty("--daraja", 2)) — faqat qiymat oldindan noma'lum bo'lganda. Brauzer aslida qanday qiymat qo'llaganini getComputedStyle(element) aytadi.

Bu darsda

  • classList ning beshta metodi bilan class'larni qo'shasiz, olib tashlaysiz va almashtirasiz.
  • Nega className = "..." xavfli va classList undan qanday himoya qilishini bilasiz.
  • element.style bilan inline stil yozasiz va uning cheklovlarini tushunasiz.
  • CSS o'zgaruvchisini JavaScript'dan yozib, CSS'ga son uzatasiz.
  • getComputedStyle bilan elementning yakuniy stilini o'qiysiz.

Oldin bilishingiz kerak: Atributlar, xususiyatlar va dataset, Kaskad: qaysi qoida g'olib bo'ladi, CSS o'zgaruvchilari 2, Meros va qiymat hisoblanish bosqichlari.

1. Nega bu kerak?

CSS qismlarida JavaScript'ga bir nechta ish qoldirgan edik:

  • Modal oyna mashqida "Qo'llash" tugmasi bor edi: "taomlarni haqiqatan yashirish — JavaScript ishi".
  • View Transitions darsida document.body.classList.toggle("katta") qatorini "aynan ko'chiring" degan edik.
  • CSS o'zgaruvchilari 2 darsida setProperty va getPropertyValue ni faqat tanishtirdik.
  • Meros va qiymat bosqichlari darsida getComputedStyle ni DevTools konsolida sinagandik.
  • Kaskad darsida inline stil "yopishqoq" ekanini va u ko'pincha JavaScript orqali paydo bo'lishini aytgandik.

Bugun bularning hammasi bitta tizimga yig'iladi. Asosiy g'oya o'sha ikki darsda — CSS o'zgaruvchilari va View Transitions — ham aytilgan edi: JavaScript holatni almashtiradi, ko'rinishni CSS hal qiladi.

Hayotdan o'xshatish: choyxona zalidagi chiroqlar. Otabek chiroqni yoqish uchun elektr simlarini qayta ulamaydi — u faqat kalitni bosadi. Qaysi lampochka, qanday rang, qancha yorug'lik — buni elektrchi oldindan o'rnatib qo'ygan. JavaScript — kalitni bosadigan Otabek, class — kalit, CSS — elektrchi o'rnatgan tizim. Otabek har kuni simlarga tegsa (inline stil), bir kun kimdir chiroqni o'zgartirmoqchi bo'lganda nima qayerga ulanganini topa olmaydi.

Diagrammada ishning bo'linishi — yuqoridan pastga:

flowchart TD
  H["Hodisa: tugma bosildi, ma'lumot keldi"]
  J["JavaScript: holatni belgilaydi"]
  C["class, data-*, aria-*"]
  V["CSS o'zgaruvchisi: --daraja"]
  S["CSS fayl: qoidalar"]
  E["Ekran"]
  H --> J
  J --> C
  J -->|"faqat son, rang kerak bo'lsa"| V
  C --> S
  V --> S
  S --> E

2. className — hamma class bitta satrda

O'tgan darsda ko'rdingiz: class atributining xususiyati — className. U barcha class'larni bitta satr sifatida beradi:

html
<li id="manti" class="taom-karta yangi mashhur">Manti</li>
<script>
  const manti = document.querySelector("#manti");
  console.log(manti.className);

  manti.className = "achchiq";
  console.log(manti.className);
</script>

Konsolda:

text
taom-karta yangi mashhur
achchiq

Maqsad — achchiq ni qo'shish edi. Lekin className ga yozish butun satrni almashtirdi: taom-karta, yangi, mashhur — hammasi ketdi. Natijada karta o'z bezagini yo'qotdi. Satrni qo'lda bo'lib, qo'shib, qayta yig'ish mumkin, lekin noqulay va xatoga moyil. Shuning uchun classList bor.

3. classList — class'lar ro'yxati

3.1 Qo'shish, olib tashlash, tekshirish

classList — elementning class'lari ro'yxati. U DOMTokenList degan turdagi obyekt: massivga o'xshaydi va har class bilan alohida ishlaydigan metodlari bor:

html
<li id="manti" class="taom-karta">Manti</li>
<script>
  const manti = document.querySelector("#manti");
  console.log(manti.classList);

  manti.classList.add("yangi", "mashhur");
  console.log(manti.classList);

  manti.classList.add("yangi");
  console.log(manti.classList.length);

  manti.classList.remove("mashhur", "yoq-class");
  console.log(manti.classList.contains("mashhur"));
  console.log(manti);
</script>

Konsolda:

text
DOMTokenList(1) ['taom-karta']
DOMTokenList(3) ['taom-karta', 'yangi', 'mashhur']
3
false
<li id="manti" class="taom-karta yangi">Manti</li>
  • add(...) — bir yoki bir nechta class qo'shadi. Bor class'ni qayta qo'shsa — hech narsa bo'lmaydi (uzunlik 3 da qoldi, takror yo'q).
  • remove(...) — olib tashlaydi. Yo'q class'ni o'chirmoqchi bo'lsa ham xato bermaydi.
  • contains(nom) — bormi: true yoki false. Bu matches(".mashhur") bilan bir xil savol, faqat bitta class uchun va tezroq.

Boshqa class'lar joyida qoldi — className dagi muammo yo'q.

3.2 toggle — almashtirgich

toggle(nom) class bo'lsa — olib tashlaydi, bo'lmasa — qo'shadi. Natijada true ("endi bor") yoki false ("endi yo'q") qaytaradi. View Transitions darsida ko'chirgan classList.toggle("katta") qatori aynan shu.

Quyidagi oynada Tugadi / Bor tugmasini bir necha marta bosing. «Bahor»dagi tugadi class'i (Global atributlar darsidagi porsiya g'oyasining CSS tomoni) kartani xiralashtiradi:

html
<style>
  .taom-karta { padding: 8px; border: 1px solid #c9d6cf; }
  .taom-karta.tugadi { opacity: 0.4; text-decoration: line-through; }
</style>
<article class="taom-karta">
  <h3>Manti</h3>
  <p>30 000 so'm</p>
</article>
<button type="button">Tugadi / Bor</button>
<script>
  const karta = document.querySelector(".taom-karta");
  document.querySelector("button")
    .addEventListener("click", () => {
      const tugadimi = karta.classList.toggle("tugadi");
      console.log("tugadi:", tugadimi, karta.classList);
    });
</script>

Birinchi bosishda karta xiralashadi va chiziladi, konsolda tugadi: true DOMTokenList(2) ['taom-karta', 'tugadi']. Ikkinchi bosishda — asl holat va tugadi: false. addEventListener — o'tgan darslardagi qolip, to'liq — addEventListener asoslari darsida.

toggle ning ikkinchi argumenti uni majburlaydi — xuddi toggleAttribute dagidek: toggle("tugadi", true) — "bo'lsin", toggle("tugadi", false) — "bo'lmasin". Bu juda qulay: shartni to'g'ridan-to'g'ri bersangiz bo'ladi, if/else kerak emas:

html
<style>
  .tugadi { opacity: 0.4; }
</style>
<article class="taom-karta" data-porsiya="0"><h3>Manti</h3></article>
<article class="taom-karta" data-porsiya="5"><h3>Osh</h3></article>
<script>
  for (const karta of document.querySelectorAll(".taom-karta")) {
    const porsiya = Number(karta.dataset.porsiya);
    karta.classList.toggle("tugadi", porsiya === 0);
  }
  console.log(document.querySelectorAll(".tugadi").length);
</script>

Konsolda:

text
1

porsiya === 0 — true yoki false. Manti uchun true — class qo'shildi, osh uchun false — qo'shilmadi (bo'lsa olib tashlanardi). Bitta qator ikkala holatni ham hal qiladi.

3.3 replace va ro'yxat sifatida

html
<li id="lagmon" class="taom-karta yangi">Lag'mon</li>
<script>
  const lagmon = document.querySelector("#lagmon");
  console.log(lagmon.classList.replace("yangi", "mashhur"));
  console.log(lagmon.classList.replace("yoq", "achchiq"));
  console.log(lagmon.classList.value);

  for (const nom of lagmon.classList) {
    console.log("class:", nom);
  }
  console.log(lagmon.classList[0], [...lagmon.classList]);
</script>

Konsolda:

text
true
false
taom-karta mashhur
class: taom-karta
class: mashhur
taom-karta (2) ['taom-karta', 'mashhur']
  • replace(eski, yangi) — almashtiradi va true qaytaradi. Eski class bo'lmasa — hech narsa qilmaydi, false qaytaradi (achchiq qo'shilmadi).
  • value — hamma class'lar bitta satrda, className bilan bir xil.
  • for...of, indeks va spread — xuddi NodeList dagidek (Elementlarni tanlash).

Tekshirib ko'ring: el da class yo'q. el.classList.toggle("ochiq") ikki marta ketma-ket chaqirildi. Natijalar va oxirgi holat qanday?

Javob

Birinchi chaqiruv — true (qo'shildi), ikkinchisi — false (olib tashlandi). Oxirida class yo'q — boshlang'ich holat. toggle har chaqirilganda holatni teskarisiga almashtiradi.

3.4 Bitta class — ko'p element: filtr

Modal oyna mashqidagi filtrni eslang: "faqat achchiq taomlar" tanlansa, qolganlari yashirinishi kerak edi. Har kartani alohida yashirish mumkin. Lekin undan ham sodda yo'l bor: otaga bitta class qo'yish va qolganini CSS'ga topshirish. Tugmani bosib ko'ring:

html
<style>
  .faqat-achchiq > :not(.achchiq) { display: none; }
  [aria-pressed="true"] { background: #2f6b3a; color: #fffaf0; }
</style>
<button type="button" aria-pressed="false">Faqat achchiq</button>
<ul id="menyu">
  <li class="taom-karta">Osh</li>
  <li class="taom-karta achchiq">Lag'mon</li>
  <li class="taom-karta">Manti</li>
</ul>
<script>
  const menyu = document.querySelector("#menyu");
  const tugma = document.querySelector("button");
  tugma.addEventListener("click", () => {
    const yoqildi = menyu.classList.toggle("faqat-achchiq");
    tugma.setAttribute("aria-pressed", yoqildi);
    console.log("filtr:", yoqildi);
  });
</script>

Bosganda faqat Lag'mon qoladi va tugma yashil bo'ladi, konsolda filtr: true. Yana bosing — hamma taom qaytadi. JavaScript bitta class va bitta atributni o'zgartirdi; qaysi taom ko'rinishini CSS selektor hal qildi. Taom 3 ta emas, 300 ta bo'lsa ham kod o'zgarmaydi.

aria-pressed — tugmaning "bosilgan/bosilmagan" holati (ARIA asoslari). U boolean atribut emas, shuning uchun setAttribute true ni "true" satriga aylantiradi — o'tgan darsdagi qoida. faqat-achchiq — shu namoyish uchun class nomi.

4. classList xatolari

Class nomida bo'sh joy bo'lishi mumkin emas: bo'sh joy — class'lar orasidagi ajratgich. Shuning uchun:

html
<li id="manti">Manti</li>
<script>
  const manti = document.querySelector("#manti");
  manti.classList.add("taom-karta yangi");
</script>

Konsolda:

text
Uncaught InvalidCharacterError: Failed to execute 'add' on 'DOMTokenList': The token provided ('taom-karta yangi') contains HTML space characters, which are not valid in tokens.

Tarjimasi: "DOMTokenList da add ni bajarib bo'lmadi: berilgan token ('taom-karta yangi') HTML bo'sh joy belgilarini o'z ichiga oladi, ular tokenda yaroqsiz". Token — ro'yxatdagi bitta so'z, bu yerda bitta class nomi. Xabar sizga aytyapti: siz ikki class'ni bitta satrga yozdingiz. Tuzatish: alohida argumentlar — add("taom-karta", "yangi").

Bo'sh satr ham xato beradi — add("") uchun Uncaught SyntaxError: ... The token provided must not be empty. Bu ko'pincha o'zgaruvchi bo'sh qolganda chiqadi.

Uchinchi xato esa jim: add(".yangi") — nuqta bilan. Xato chiqmaydi, lekin elementga .yangi degan nuqtali class qo'shiladi: class=".yangi". CSS'dagi .yangi selektori unga mos kelmaydi. Nuqta — faqat selektorda (querySelector(".yangi")), classList ga esa nomning o'zi beriladi. getElementById ga # yozish xatosining egizagi.

5. element.style — inline stil

5.1 Yozish

Har HTML elementda style xususiyati bor. Unga yozilgan narsa HTML'dagi style="..." atributiga — inline stilga tushadi:

html
<p id="aksiya">Bugun ko'k choy bepul!</p>
<script>
  const aksiya = document.querySelector("#aksiya");
  aksiya.style.color = "#b4461a";
  aksiya.style.fontWeight = "700";
  aksiya.style.setProperty("background-color", "#fffaf0");
  console.log(aksiya.getAttribute("style"));
</script>

Konsolda:

text
color: rgb(180, 70, 26); font-weight: 700; background-color: rgb(255, 250, 240);

Nomlarga qarang:

  • JavaScript'da CSS xususiyati nomi camelCase: font-weight → fontWeight, background-color → backgroundColor. Sabab dataset dagidek: chiziqcha — ayirish belgisi.
  • setProperty("background-color", ...) esa CSS'dagi asl nomni qabul qiladi. Ikkalasi bir xil ishlaydi.
  • Brauzer hex rangni rgb(...) ga aylantirib saqladi. Ma'nosi bir xil.

5.2 Uchta jim tuzoq

html
<p id="narx" style="width: 200px">35 000 so'm</p>
<script>
  const narx = document.querySelector("#narx");
  narx.style.width = 100;
  console.log(narx.style.width);

  narx.style.color = "qizil";
  console.log(JSON.stringify(narx.style.color));

  console.log(JSON.stringify(narx.style.fontSize));
</script>

Konsolda:

text
200px
""
""
  • width = 100 — birliksiz son. CSS'da width: 100 yaroqsiz, brauzer uni jimgina tashlab yubordi — eski 200px qoldi. To'g'risi: "100px". Faqat birliksiz xususiyatlar (opacity, zIndex, lineHeight) son qabul qiladi.
  • "qizil" — CSS rang nomi emas. Yana jim rad etildi. Xato chiqmaydi — DevTools'da ham ko'rinmaydi.
  • style.fontSize — bo'sh satr, garchi matnning shrift o'lchami bor bo'lsa ham. style faqat inline stilni o'qiydi. CSS faylidan, meros orqali kelgan qiymatni u bilmaydi. Haqiqiy qiymat — getComputedStyle da («getComputedStyle» bo'limi).

5.3 Olib tashlash va cssText

Inline stilni olib tashlash uchun bo'sh satr yoki removeProperty:

html
<p id="aksiya" style="color: #b4461a; font-weight: 700">Aksiya</p>
<script>
  const aksiya = document.querySelector("#aksiya");
  aksiya.style.color = "";
  aksiya.style.removeProperty("font-weight");
  console.log(JSON.stringify(aksiya.getAttribute("style")));

  aksiya.style.cssText = "color: #2f6b3a; padding: 4px";
  console.log(aksiya.getAttribute("style"));
</script>

Konsolda:

text
""
color: rgb(47, 107, 58); padding: 4px;

Birinchi qatorda bo'sh satr (JSON.stringify uni qo'shtirnoqda ko'rsatdi): inline stil qolmadi, element yana CSS faylga bo'ysunadi. cssText — butun inline stil bitta satrda. Unga yozish hamma inline xususiyatlarni almashtiradi — xuddi className kabi. Ehtiyot bo'ling.

5.4 Nega inline stil — oxirgi chora

Kaskad darsidan: inline stil CSS fayldagi qoidadan kuchli. Uni faqat !important yengadi. JavaScript bir marta element.style.color = "red" yozsa, keyin CSS'da shu elementning rangini o'zgartirib bo'lmaydi — "nega rangim ishlamayapti?" degan savol tug'iladi. Dizayner Nodira ranglarni yangilaydi, bitta tugma esa eski rangda qoladi.

Yana bir sabab — xavfsizlik siyosati. «Bahor»dagi CSP (HTML xavfsizligi) HTML'dagi style="..." ni to'sadi. Chrome 154 da tekshirdik: style-src da 'unsafe-inline' bo'lmasa, setAttribute("style", ...) ham to'siladi. element.style.color = ..., setProperty va cssText esa ishlaydi — CSP skript orqali stilga tegishni to'smaydi. Demak, JavaScript'dan stil kerak bo'lsa — faqat style xususiyati orqali.

Qachon style to'g'ri tanlov? Qiymat oldindan noma'lum bo'lganda: sichqoncha joyi, yuklanish foizi, foydalanuvchi tanlagan rang. "Qizil yoki yashil" kabi oldindan ma'lum holatlar uchun — class.

Tekshirib ko'ring: Dasturchi xatoli maydonni input.style.borderColor = "red" bilan qizil qildi. Ertasi kuni dizayner CSS'da xato rangini #b4461a ga o'zgartirdi. Nima bo'ladi?

Javob

Maydon qizil (red) qoladi: inline stil CSS fayldagi qoidadan kuchli. Bundan tashqari, rangdan ekran o'quvchi hech narsa bilmaydi. To'g'ri yo'l — o'tgan darsdagi aria-invalid="true" va CSS'da [aria-invalid="true"] qoidasi: rang CSS'da, holat atributda.

6. CSS o'zgaruvchilari — JavaScript'dan CSS'ga son

Ba'zan qiymat haqiqatan dinamik bo'ladi, lekin uni qanday chizishni CSS hal qilishi kerak. Buning eng toza yo'li — CSS o'zgaruvchisi. CSS o'zgaruvchilari 2 darsida ko'rgandingiz: JavaScript setProperty("--nom", qiymat) bilan yozadi, CSS esa var(--nom) bilan ishlatadi.

«Bahor» kartasida achchiqlik shkalasi bor: --daraja 0 dan 3 gacha, CSS uni kenglikka aylantiradi. + va − ni bosib ko'ring:

html
<style>
  .shkala { height: 12px; background: #e8f1ec; }
  .shkala span {
    display: block;
    height: 100%;
    background: #b4461a;
    width: calc(var(--daraja, 0) * 100% / 3);
  }
</style>
<p>Lag'mon achchiqligi:</p>
<div class="shkala"><span></span></div>
<button type="button" id="kam">−</button>
<button type="button" id="kop">+</button>
<script>
  const shkala = document.querySelector(".shkala");
  let daraja = 1;
  shkala.style.setProperty("--daraja", daraja);
  console.log(shkala.style.getPropertyValue("--daraja"));

  function darajaniOzgartir(farq) {
    daraja = Math.min(3, Math.max(0, daraja + farq));
    shkala.style.setProperty("--daraja", daraja);
    console.log("daraja:", daraja);
  }
  document.querySelector("#kam")
    .addEventListener("click", () => darajaniOzgartir(-1));
  document.querySelector("#kop")
    .addEventListener("click", () => darajaniOzgartir(1));
</script>

Konsolda:

text
1

Har + shkalani uchdan biriga to'ldiradi, 3 dan oshmaydi (Math.min, Math.max — Math obyekti). JavaScript faqat birliksiz son yozdi. Rang, balandlik, "uchdan bir" hisobi — hammasi CSS'da. Dizayner shkalani doira qilmoqchi bo'lsa, JavaScript'ga tegmaydi.

Ikki fakt:

  • setProperty("--daraja", 1) — son satrga aylanadi, CSS'ga 1 bo'lib tushadi. -- bilan boshlangan nom faqat setProperty orqali yoziladi: style.--daraja degan yozuv JavaScript'da yo'q.
  • --daraja inline stilda turibdi (style="--daraja: 1;"), lekin u ranglar va o'lchamlarni emas, faqat sonni saqlaydi. Shuning uchun inline stilning "yopishqoqligi" bu yerda zarar qilmaydi.

Tekshirib ko'ring: Yuklanish chizig'i (progress bar) uchun ikki variant bor: (a) chiziq.style.width = foiz + "%"; (b) chiziq.style.setProperty("--foiz", foiz) va CSS'da width: calc(var(--foiz) * 1%). Ikkalasi ham ishlaydi. Qaysi biri dizayner uchun qulayroq?

Javob

(b). Unda JavaScript faqat sonni beradi, uni qanday chizish — CSS'da: dizayner chiziqni kenglik o'rniga balandlik bilan yoki scale bilan chizmoqchi bo'lsa, faqat CSS'ni o'zgartiradi. (a) da esa "foiz — bu kenglik" degan qaror JavaScript ichiga yozilgan. Ikkalasi ham inline stil, lekin (b) ko'rinish haqidagi qarorni CSS'da qoldiradi.

7. getComputedStyle — brauzer aslida nimani qo'lladi

7.1 Yakuniy qiymatlar

element.style faqat inline stilni biladi. Elementning yakuniy stili — CSS fayllar, meros, kaskad va inline hammasi hisoblangandan keyingi natija — getComputedStyle(element) da. Meros va qiymat bosqichlari darsida uni DevTools'da sinagandik, endi kodda:

html
<style>
  .karta { color: #2f6b3a; width: 50%; padding: 1rem; }
  .karta::before { content: "★ "; }
</style>
<div style="width: 600px">
  <p class="karta">Osh</p>
</div>
<script>
  const karta = document.querySelector(".karta");
  console.log(JSON.stringify(karta.style.color));

  const uslub = getComputedStyle(karta);
  console.log(uslub.color, uslub.width, uslub.paddingTop);
  console.log(uslub.getPropertyValue("font-size"));

  const oldi = getComputedStyle(karta, "::before");
  console.log(oldi.content);
</script>

Konsolda:

text
""
rgb(47, 107, 58) 300px 16px
16px
"★ "
  • style.color bo'sh — rang CSS fayldan keladi, inline emas.
  • getComputedStyle haqiqiy rangni berdi — rgb(...) ko'rinishida, hex emas.
  • width: 50% → 300px: Meros va qiymat bosqichlari darsidagi hal qilingan qiymat — piksellarda.
  • 1rem → 16px. Qisqa xususiyat (padding) o'rniga aniq tomonni so'rash ishonchliroq: paddingTop.
  • Ikkinchi argument — pseudo-element: ::before ning content i qo'shtirnoqlari bilan keladi.

CSS o'zgaruvchisi ham shu yerdan o'qiladi: getComputedStyle(document.documentElement).getPropertyValue("--rang-asosiy") — CSS o'zgaruvchilari 2 darsidagi misol.

7.2 Faqat o'qish uchun

getComputedStyle qaytargan obyekt jonli: element stili o'zgarsa, u ham yangilanadi. Lekin unga yozib bo'lmaydi:

html
<p id="osh">Osh</p>
<script>
  const uslub = getComputedStyle(document.querySelector("#osh"));
  uslub.color = "red";
</script>

Konsolda:

text
Uncaught NoModificationAllowedError: Failed to set a named property 'color' on 'CSSStyleDeclaration': These styles are computed, and therefore the 'color' property is read-only.

Tarjimasi: "CSSStyleDeclaration da 'color' xususiyatini o'rnatib bo'lmadi: bu stillar hisoblangan, shuning uchun 'color' faqat o'qish uchun". Yozish — element.style yoki class orqali.

7.3 Qachon ishlatiladi va narxi

getComputedStyle kerak bo'ladigan holatlar: elementning haqiqiy rangini yoki o'lchamini bilish, animatsiyani hozirgi joyidan davom ettirish, tema hozir qorong'imi — tekshirish (bu darsning «Portfolio qadami»).

Narxi bor: haqiqiy qiymatni berish uchun brauzer ba'zan sahifani qaytadan o'lchashi (layout) kerak. Sikl ichida "yoz — o'qi — yoz — o'qi" qilinsa, sahifa sekinlashadi. Buni Rendering pipeline va layout thrashing darsida chuqur ko'ramiz. Hozircha odat: kerak bo'lsagina o'qing va siklda emas.

Tekshirib ko'ring: getComputedStyle(el).display "none" qaytardi. Bu element HTML'da hidden atributiga ega degani-mi?

Javob

Shart emas. display: none ko'p yo'l bilan kelishi mumkin: hidden atributi, CSS fayldagi qoida, ota-elementdagi filtr class'i (masalan yuqoridagi .faqat-achchiq), inline stil. getComputedStyle faqat natijani aytadi, sababini emas. Sababni DevTools → Elements → Computed yorlig'ida ko'rasiz: qiymat yonidagi strelka qaysi qoidadan kelganini ko'rsatadi.

7.4 DevTools'da class va stillarni sinash

Kodga yozishdan oldin class'ni kompyuterda, DevTools'da sinab ko'rish qulay. DevTools'da CSS bilan ishlash darsidagi Styles panelida ikki kichik tugma bor:

  • .cls — tanlangan elementning class'lari ro'yxatini ochadi. Har class yonida belgilash katagi bor: uni olib tashlasangiz, class vaqtincha o'chadi — xuddi classList.toggle. Pastdagi maydonga yangi nom yozib, Enter bossangiz — classList.add.
  • :hov — elementni :hover yoki :focus holatiga majburlaydi. JavaScript bilan bog'liq emas, lekin "tugma bosilganda nima bo'ladi?" ni sinashda yonma-yon ishlatiladi.

JavaScript class o'zgartirganda Elements panelida o'zgargan atribut bir lahza binafsha rangda yonib o'chadi (DOM daraxti darsida ko'rgandingiz). «Faqat achchiq» tugmasini o'z sahifangizda bosib, ul dagi class qanday paydo bo'lib, yo'qolishini kuzating.

Inline stillar ham shu yerda ko'rinadi: Styles panelining eng tepasidagi element.style { } bloki — element.style yozgan hamma narsa. CSS fayldagi qoida ustidan chizilgan bo'lsa (qiymati o'chirilgan chiziq bilan), demak inline stil uni yenggan.

8. Ko'rsatish va yashirish: qaysi yo'l?

Elementni yashirishning to'rt yo'li bor:

Usul Qachon Kamchiligi
el.hidden = true Oddiy "ko'rinsin/ko'rinmasin" CSS'dagi display uni bosib ketishi mumkin
Class (classList.toggle) Animatsiya, bir nechta holat, filtr CSS'da qoida kerak
aria-* / data-* + CSS Holat ma'noli: ochiq menyu, xato —
el.style.display = "none" Deyarli hech qachon Inline — yopishqoq

Birinchi qatordagi kamchilikni ko'ring — bu real loyihalarda tez-tez uchraydi:

html
<style>
  .karta { display: flex; gap: 8px; }
</style>
<div class="karta" hidden>
  <span>Osh</span><span>35 000</span>
</div>
<script>
  const karta = document.querySelector(".karta");
  console.log(karta.hidden, getComputedStyle(karta).display);
</script>

Konsolda:

text
true flex

hidden — true, lekin karta ko'rinib turibdi! Brauzerning hidden uchun qoidasi ([hidden] { display: none }) — eng kuchsiz, brauzer stili. Sizning CSS faylingizdagi display: flex uni yengdi (display va yashirish). Tuzatish: CSS'ga [hidden] { display: none !important; } qo'shish — ko'p loyihalarning reset faylida shunday qator bor (CSS reset).

9. Ko'p uchraydigan xatolar

9.1 className ga yozib, boshqa class'larni o'chirish

el.className = "yangi" — eski class'lar ketadi. Tuzatish: el.classList.add("yangi").

9.2 add("a b") va add(".a")

Birinchisi — InvalidCharacterError, ikkinchisi — jim noto'g'ri class («classList xatolari» bo'limi). Har class — alohida argument, nuqtasiz.

9.3 Rangni JavaScript'da yozish

el.style.color = "#b4461a" — rang endi ikki joyda: CSS'da va JS'da. Dizayn o'zgarganda biri unutiladi. Tuzatish: class yoki aria-*/data-* + CSS qoidasi.

9.4 Birliksiz qiymat

el.style.width = 100 jimgina rad etiladi. Tuzatish: "100px" yoki template literal: `${eni}px`.

9.5 style dan CSS fayldagi qiymatni o'qish

el.style.fontSize — "". Tuzatish: getComputedStyle(el).fontSize.

10. Mashqlar

1-mashq (oson): Class'larni boshqaring

Kartadan yangi ni olib tashlang, mashhur va achchiq ni qo'shing, keyin achchiq borligini tekshiring va class'lar ro'yxatini chiqaring. Kutilgan natija:

text
true
DOMTokenList(3) ['taom-karta', 'mashhur', 'achchiq']
html
<article class="taom-karta yangi"><h3>Lag'mon</h3></article>
<script>
  const karta = document.querySelector(".taom-karta");
  // shu yerga yozing
</script>
Yechim
html
<article class="taom-karta yangi"><h3>Lag'mon</h3></article>
<script>
  const karta = document.querySelector(".taom-karta");
  karta.classList.remove("yangi");
  karta.classList.add("mashhur", "achchiq");
  console.log(karta.classList.contains("achchiq"));
  console.log(karta.classList);
</script>

Konsolda:

text
true
DOMTokenList(3) ['taom-karta', 'mashhur', 'achchiq']

remove + add o'rniga replace("yangi", "mashhur") va add("achchiq") ham bo'ladi — natija bir xil.

2-mashq (o'rta): Narx bo'yicha belgilash

30 000 so'mdan qimmat taomlarga qimmat class'ini qo'ying, qolganlaridan olib tashlang — bitta toggle qatori bilan. Oxirida qimmat taomlar nomini chiqaring. Kutilgan natija: Qimmat: Osh.

Ishora: narx data-narx da (dataset), Number() bilan songa aylantiring; toggle(nom, shart) — «toggle — almashtirgich» bo'limi.

html
<style>
  .qimmat { font-weight: 700; }
</style>
<ul id="menyu">
  <li class="taom-karta" data-narx="35000">Osh</li>
  <li class="taom-karta qimmat" data-narx="28000">Lag'mon</li>
  <li class="taom-karta" data-narx="30000">Manti</li>
</ul>
<script>
  // shu yerga yozing
</script>
Yechim
html
<style>
  .qimmat { font-weight: 700; }
</style>
<ul id="menyu">
  <li class="taom-karta" data-narx="35000">Osh</li>
  <li class="taom-karta qimmat" data-narx="28000">Lag'mon</li>
  <li class="taom-karta" data-narx="30000">Manti</li>
</ul>
<script>
  for (const taom of document.querySelectorAll(".taom-karta")) {
    const narx = Number(taom.dataset.narx);
    taom.classList.toggle("qimmat", narx > 30000);
  }
  for (const taom of document.querySelectorAll(".qimmat")) {
    console.log(`Qimmat: ${taom.textContent}`);
  }
</script>

Konsolda:

text
Qimmat: Osh

Lag'mon'da qimmat noto'g'ri qo'yilgan edi — toggle(..., false) uni olib tashladi. Manti 30 000 — "qimmatroq" emas, teng: > shartiga tushmadi. add bilan yozganda Lag'mon xatosi tuzalmasdi — toggle ning ikkinchi argumenti aynan shuning uchun qulay. qimmat — mashq uchun class nomi.

3-mashq (qiyin): Asosiy rangni almashtiring

:root dagi --rang-asosiy ni o'qing va chiqaring. Keyin JavaScript'dan uni #1a5d1a ga o'zgartiring va sarlavhaning haqiqiy rangini (getComputedStyle) chiqaring. Kutilgan natija:

text
#2f6b3a
rgb(26, 93, 26)

Ishora: :root — JavaScript'da document.documentElement; o'zgaruvchi yozish — style.setProperty, o'qish — getComputedStyle(...).getPropertyValue.

html
<style>
  :root { --rang-asosiy: #2f6b3a; }
  h2 { color: var(--rang-asosiy); }
</style>
<h2>«Bahor» menyusi</h2>
<script>
  // shu yerga yozing
</script>
Yechim
html
<style>
  :root { --rang-asosiy: #2f6b3a; }
  h2 { color: var(--rang-asosiy); }
</style>
<h2>«Bahor» menyusi</h2>
<script>
  const ildiz = document.documentElement;
  const rang = getComputedStyle(ildiz)
    .getPropertyValue("--rang-asosiy");
  console.log(rang);

  ildiz.style.setProperty("--rang-asosiy", "#1a5d1a");
  const sarlavha = document.querySelector("h2");
  console.log(getComputedStyle(sarlavha).color);
</script>

Konsolda:

text
#2f6b3a
rgb(26, 93, 26)

O'zgaruvchi qiymati yozilganidek keladi (#2f6b3a), sarlavhaning rangi esa hisoblangan rgb(...). Bitta setProperty sahifadagi --rang-asosiy ishlatgan hamma joyni o'zgartirdi — o'zgaruvchilarning kuchi shunda. #1a5d1a — «Bahor»ning --rang-asosiy-toq rangi.

4-mashq: Portfolio qadami — qorong'i temani yoqish funksiyasi

Qorong'i rejim darsida portfolio CSS'ini tayyorlagansiz: <html data-tema="qorongi"> bo'lsa, sayt tizimga qaramay qorong'i bo'ladi. O'shanda atributni DevTools'da qo'lda yozgandingiz. Endi uni JavaScript qo'ysin.

asosiy.js ga temaniQoy(tema) funksiyasini yozing:

  1. tema — "yorug", "qorongi" yoki "tizim".
  2. "yorug" yoki "qorongi" bo'lsa — <html> ga data-tema ni shu qiymat bilan qo'ying (dataset).
  3. "tizim" bo'lsa — atributni olib tashlang: CSS'dagi color-scheme: light dark yana tizimga ergashadi.
  4. Funksiya <html> ning hisoblangan color-scheme ini qaytarsin (getComputedStyle(...).colorScheme) — tekshirish uchun.

Funksiyani hozircha chaqirmang: uni tugma bosilganda addEventListener asoslari darsida chaqiramiz, tanlovni saqlashni esa localStorage bilan 11-qismda qo'shamiz. Sinash — DevTools konsolida: temaniQoy("qorongi").

Nega class emas, data-tema? CSS tayyor va u [data-tema="qorongi"] ni kutadi. Bundan tashqari, tema — uch qiymatli holat; uch class'ni (yorug, qorongi, tizim) bir-biriga qarshi toggle qilishdan bitta atributning qiymati soddaroq. Real loyihalarda class="dark" ham ko'p uchraydi — g'oya bir xil.

Commit: JS: temani almashtirish funksiyasini qo'sh.

Yechim
js
function temaniQoy(tema) {
  const html = document.documentElement;
  if (tema === "yorug" || tema === "qorongi") {
    html.dataset.tema = tema;
  } else {
    delete html.dataset.tema;
  }
  return getComputedStyle(html).colorScheme;
}

Portfolio CSS'ining kichik nusxasida sinaymiz — fon rangi ham tekshiriladi:

html
<style>
  :root {
    color-scheme: light dark;
    --rang-fon: light-dark(#f7faf8, #16301b);
  }
  :root[data-tema="yorug"] { color-scheme: light; }
  :root[data-tema="qorongi"] { color-scheme: dark; }
  body { background: var(--rang-fon); }
</style>
<p>Portfolio sahifasi</p>
<script>
  function temaniQoy(tema) {
    const html = document.documentElement;
    if (tema === "yorug" || tema === "qorongi") {
      html.dataset.tema = tema;
    } else {
      delete html.dataset.tema;
    }
    return getComputedStyle(html).colorScheme;
  }

  console.log(temaniQoy("qorongi"));
  console.log(getComputedStyle(document.body).backgroundColor);
  console.log(temaniQoy("tizim"), document.documentElement);
</script>

Konsolda:

text
dark
rgb(22, 48, 27)
light dark <html lang="uz">…</html>

"qorongi" — fon to'q yashil bo'ldi (rgb(22, 48, 27) — #16301b). "tizim" — atribut olib tashlandi va color-scheme yana light dark. Jonli oyna sayt tomonidan doim yorug' ochiladi, shuning uchun bu yerda "tizim" yorug' ko'rinadi. Portfolio'ngizda DevTools konsolida temaniQoy("qorongi") ni yozing — butun sayt qorong'i bo'ladi; temaniQoy("tizim") — qaytadi.

Mavjud bo'lmagan qiymat (temaniQoy("kok")) ham "tizim" kabi ishlaydi — bu ataylab: noto'g'ri qiymat saytni buzmaydi, tizim rejimiga qaytaradi.

11. Real ishda

  • Har bir interaktiv komponent — menyu ochildi, tab tanlandi, karta tugadi — classList.toggle yoki aria-* atribut va CSS qoidasi bilan ishlaydi. Kod ko'rigida style.color = ... ko'rinsa, birinchi savol: "nega class emas?"
  • Tailwind kabi CSS freymvorklarida (06-qismda ko'rgansiz) JavaScript ham faqat class qo'shadi va olib tashlaydi: classList.toggle("hidden"). Qorong'i rejim ko'pincha <html class="dark"> bilan.
  • Animatsiya kutubxonalari element joyini aniqlash uchun getComputedStyle va o'lchamlarni o'qiydi, harakatni esa style.transform yoki CSS o'zgaruvchisi bilan beradi — dinamik qiymat uchun inline stilning to'g'ri ishlatilishi.
  • Freymvorklarda (React — kursda alohida o'rganamiz) className yoziladi — lekin u har safar butun ro'yxatni qayta hisoblaydi, shuning uchun bugungi className tuzog'i u yerda yo'q.
  • Intervyuda so'raladi: "element.style va getComputedStyle farqi?", "Elementni JavaScript'da qanday yashirasiz?", "Nega inline stil yomon?"

Xulosa

  • classList.add/remove/toggle/replace/contains — class'lar bilan ishlashning asosiy yo'li; className ga yozish boshqa class'larni o'chiradi.
  • toggle(nom, shart) — shartga qarab qo'shadi yoki olib tashlaydi, if/else siz.
  • Class nomida bo'sh joy va nuqta yo'q: add("a", "b").
  • element.style — faqat inline stil; camelCase nomlar, birlik majburiy, xato qiymat jim rad etiladi. Inline stil — oxirgi chora.
  • CSS o'zgaruvchisi (setProperty("--daraja", 2)) — JavaScript'dan CSS'ga dinamik son uzatishning toza yo'li.
  • getComputedStyle — yakuniy, hal qilingan qiymatlar; faqat o'qish uchun, pseudo-elementni ham o'qiydi.

Keyingi dars: Element yaratish, joylash va o'chirish — sahifaga yangi elementlar qo'shamiz: createElement, append, remove va cloneNode.

Manbalar

  • MDN: "Element: classList property", "DOMTokenList" — developer.mozilla.org
  • MDN: "HTMLElement: style property", "CSSStyleDeclaration: setProperty() method" — developer.mozilla.org
  • MDN: "Window: getComputedStyle() method" — developer.mozilla.org
  • CSSOM Standard: "Resolved values" — drafts.csswg.org/cssom
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JavaScript'da classList va stillar: class, style, CSS o'zgaruvchilari va getComputedStyle — IlmHamroh