Mundarija (36)
- Bu darsda
- 1. Nega bu kerak?
- 2. :is() — ro'yxatdan istalgani
- 2.1 Takrorni qisqartirish
- 2.2 Kechirimli ro'yxat
- 2.3 Og'irligi va cheklovi
- 3. :where() — og'irligi nol egizak
- 4. :not() — "shundan boshqa"
- 4.1 Oddiy inkor
- 4.2 Murakkab inkor va mashhur tuzoq
- 4.3 Kechirimli emas
- 5. :has() — "ichida X bor"
- 5.1 Yangi yo'nalish
- 5.2 Rasmli karta
- 5.3 Forma: xato maydonning yorlig'i
- 5.4 Tanlangan variant va miqdor so'rovi
- 5.5 Hammasi birga: xiralashadigan menyu
- 6. :has() qoidalari va tezlik
- 6.1 Uchta cheklov
- 6.2 Brauzerlarda va zaxira
- 6.3 Tezlik
- 7. Ko'p uchraydigan xatolar
- 7.1 :not(X) Y — "X ichida bo'lmagan Y" emas
- 7.2 :not() yoki :has() ichida xato
- 7.3 :has() li selektor vergulli ro'yxatda
- 7.4 body:has() hamma narsa uchun
- 7.5 :is() ichida pseudo-element
- 7.6 Yolg'iz :not()
- 8. Mashqlar
- 1-mashq (oson): Qisqartiring
- 2-mashq (o'rta): Bron formasining "Qayerda o'tirasiz?" guruhi
- 3-mashq (qiyin): Stajyorning selektorlari
- 4-mashq: Portfolio qadami — mantiqiy selektorlar
- 9. Real ishda
- Xulosa
- Manbalar
CSS :has, :is, :where va :not: mantiqiy pseudo-klasslar
Qisqacha: Mantiqiy pseudo-klasslar qavs ichiga selektorlar ro'yxatini oladi. Masalan,
:is(header, footer) auzun ro'yxatni qisqartiradi. Uning egizagi:where()xuddi shunday ishlaydi, faqat og'irligi nol. Inkor:not(.achchiq)mos kelmaganlarini tanlaydi. Eng kuchlisi:has()"ichida X bor" yoki "keyinida X turgan" elementni tanlaydi:article:has(img)— rasmli karta,label:has(~ :user-invalid)— xatoli maydonning yorlig'i.:is()va:where()ichidagi noto'g'ri selektor butun qoidani buzmaydi,:not()va:has()ichidagisi esa buzadi.
Bu darsda
:is()bilan takroriy selektorlarni qisqartirasiz va "kechirimli ro'yxat"ni tushuntirasiz.:where()ning:is()dan farqini bilasiz.:not()bilan inkor yozasiz va uning mashhur tuzog'idan qochasiz.:has()bilan ota va oldingi qo'shnini tanlaysiz: rasmli karta, xatoli maydon, tanlangan variant.:has()qoidalari va tezlik bo'yicha tavsiyalarni bilasiz.
Oldin bilishingiz kerak: Holat pseudo-klasslari, Tuzilma pseudo-klasslari, Asosiy selektorlar va kombinatorlar.
1. Nega bu kerak?
Oldingi darslardan uchta ochiq savol qoldi:
- Uzun ro'yxatlar.
header a:hover, nav a:hover, footer a:hover— bir xil qism uch marta. Yana Asosiy selektorlar darsidagi xavf: ro'yxatdagi bitta noto'g'ri selektor butun qoidani o'chiradi. - "Boshqa hammasi". Joriy sahifadan tashqari hamma havolaga hover kerak. Hozircha "shundan tashqari" deyishning yo'li yo'q.
- Orqaga qarash. Kombinatorlar faqat pastga (ota → bola) va oldinga (oldingi → keyingi) qaraydi. Holat pseudo-klasslari darsida
labelmaydondan oldin turgani uchun uni xato maydonga qarab bo'yay olmadik.
«Bahor»da Jasur aka ofitsiant Otabekka shunday topshiriqlar beradi:
- "Zal yoki ayvondagi stollarga non qo'y" — ro'yxatdan istalgani.
- "7-stoldan boshqa hamma stolga choy qo'y" — inkor.
- "Bolali oila o'tirgan stolga bolalar stulini olib bor" — stolni ichidagi odamlarga qarab tanlash.
CSS'da bu uch topshiriqqa to'rtta vosita javob beradi: :is(), :where(), :not() va :has(). Ular mantiqiy pseudo-klasslar (logical pseudo-classes) deb ataladi: ichiga selektorlarni olib, ular ustida "yoki", "emas", "ichida bor" amallarini bajaradi.
2. :is() — ro'yxatdan istalgani
2.1 Takrorni qisqartirish
:is() qavs ichidagi selektorlardan istalganiga mos elementni tanlaydi:
/* Uzun yo'l */
header a:hover,
nav a:hover,
footer a:hover {
color: #b4461a;
}
/* Xuddi shu — :is() bilan */
:is(header, nav, footer) a:hover {
color: #b4461a;
}O'qilishi: "header yoki nav yoki footer ichidagi, ustida sichqoncha turgan havola". Umumiy qism bir marta yoziladi, farq qiladigan qism — qavs ichida.
:is() selektorning istalgan joyida turadi. Ikkitasi birga bo'lsa, brauzer hamma juftlarni o'zi tuzadi:
<style>
main :is(h2, h3) :is(a, strong) {
color: #b4461a;
}
</style>
<main>
<h2>Bugun <strong>chegirma</strong></h2>
<h3><a href="menyu/">Menyuni ko'rish</a></h3>
<p>Oddiy <strong>paragraf</strong> — bunga tegmaydi.</p>
</main>Nimaga qarang: sarlavhalardagi strong va havola qizg'ish, paragrafdagi strong esa qora. Bitta qator to'rtta selektorni almashtirdi: main h2 a, main h2 strong, main h3 a, main h3 strong.
2.2 Kechirimli ro'yxat
Asosiy selektorlar darsida va'da bergan edik: vergulli ro'yxatdagi bitta xato butun qoidani o'chiradi, :is() esa bundan qutqaradi. Solishtiramiz:
<style>
/* ❌ #1-taom noto'g'ri — butun qoida tashlanadi */
h2, #1-taom { color: #b4461a; }
/* ✅ :is() ichida noto'g'ri qismni tashlab, qolganini oladi */
:is(h3, #1-taom) { color: #2f6b3a; }
</style>
<h2>Issiq taomlar</h2>
<h3>Osh</h3>Nimaga qarang: h2 qora qoldi, h3 esa yashil. Chrome'da tekshirdik: DevTools ikkinchi qoidani :is(h3) deb ko'rsatdi — noto'g'ri qism jimgina olib tashlandi. Birinchi qoida esa umuman yo'q.
Bunday ro'yxat kechirimli (forgiving selector list) deb ataladi. Bu qachon kerak? Ro'yxatga yangi yoki faqat ba'zi brauzerlarda bor selektor qo'shganda. Eski brauzer uni tushunmasa, qolgan qism baribir ishlaydi.
2.3 Og'irligi va cheklovi
Og'irlik haqida bitta gap: :is() o'z ichidagi eng og'ir selektorning og'irligini oladi. Masalan, :is(p, #asosiy) oddiy p ni tanlaganda ham id kabi og'ir bo'ladi. Bu qanday hisoblanishini Specificity darsida ko'ramiz.
Cheklovi: :is() ichida pseudo-element (keyingi darsdagi ::before kabi) ishlamaydi — brauzer uni kechirimli ro'yxatdan jimgina chiqarib tashlaydi. Chrome'da tekshirdik.
3. :where() — og'irligi nol egizak
:where() :is() bilan bir xil ishlaydi: o'sha "yoki", o'sha kechirimli ro'yxat. Farqi — bitta: :where() ning og'irligi nol. Unda qanday selektor yozilmasin, u to'qnashuvda hech narsa qo'shmaydi.
Nega bu kerak? Ba'zi qoidalar "boshlang'ich" bo'ladi: hamma joyga umumiy ko'rinish beradi, keyin esa aniq joylarda o'zgartiriladi. :where() li qoidani har qanday oddiy qoida bosib keta oladi.
/* Boshlang'ich qoida: hamma sarlavhalar yashil */
:where(h1, h2, h3) {
color: #2f6b3a;
}Bunday qoidalarni CSS reset va katta kutubxonalarda ko'p uchratasiz. Qisqasi: :is() — eng og'ir argumentcha, :where() — nol; hisobi Specificity darsida.
Tekshirib ko'ring:
:where(h2, #1-taom) { color: #2f6b3a; }— bu qoidah2ni yashil qiladimi?
Javob
Ha. :where() ham :is() kabi kechirimli: noto'g'ri #1-taom tashlanadi, h2 qoladi. Chrome'da tekshirdik. Oddiy vergulli ro'yxat bo'lganda edi, h2 ham bo'yalmasdi.
4. :not() — "shundan boshqa"
4.1 Oddiy inkor
:not() qavs ichidagi selektorga mos kelmaydigan elementni tanlaydi:
li:not(:last-child)— oxirgisidan boshqa hamma qator. Qatorlar orasidagi chiziq uchun — Tuzilma pseudo-klasslari darsidagili:last-child { border-bottom: 0 }ning bitta qatorli varianti.a:not([href^="https://"])— boshqa saytga olib bormaydigan havolalar.input:not([type="checkbox"], [type="radio"])— qavs ichida ro'yxat ham bo'ladi: "na checkbox, na radio" — ya'ni matn yoziladigan maydonlar.
Jasur akaning ikkinchi topshirig'i — joriy sahifadan boshqa havolalarga hover:
<style>
nav a {
color: #2f6b3a;
padding: 2px 6px;
}
nav a:not([aria-current="page"]):hover {
background-color: #fffaf0;
color: #b4461a;
}
nav [aria-current="page"] {
color: #1f2a24;
font-weight: bold;
}
</style>
<nav aria-label="Asosiy menyu">
<a href="../">Bosh sahifa</a>
<a href="./" aria-current="page">Menyu</a>
<a href="../bron/">Stol band qilish</a>
</nav>Nimaga qarang: "Bosh sahifa" va "Stol band qilish" ustida fon va rang o'zgaradi. "Menyu" esa jim turadi — mehmon allaqachon shu sahifada, uni "bosing" deb chaqirishning ma'nosi yo'q. :not() boshqa pseudo-klasslar bilan bir qatorda yopishib turadi: a:not(...):hover.
4.2 Murakkab inkor va mashhur tuzoq
Qavs ichiga kombinatorli selektor ham yozish mumkin. a:not(nav a) — "nav ichida bo'lmagan havola". Chrome'da tekshirdik: logotip havolasi tanlandi, menyu havolasi esa yo'q.
Endi uning "o'xshashi"ni ko'ring: :not(nav) a. Ko'pchilik uni ham "nav ichida bo'lmagan havola" deb o'qiydi. Aslida u "nav bo'lmagan qandaydir ota ichidagi havola" degani. Menyu havolasining otalari orasida header, body, html bor — ular nav emas. Demak, shart bajarildi. Chrome'da tekshirdik: :not(nav) a menyu havolasini ham, logotipni ham tanladi.
Qoida: "X ichida bo'lmagan Y" — Y:not(X Y). Inkor butun zanjirni o'rab olsin.
4.3 Kechirimli emas
:not() :is() dan farqli — kechirimsiz. Chrome'da tekshirdik: :not(h2, #1-taom) butun qoidani tashlab yubordi. Ichidagi har bir selektor to'g'ri bo'lishi shart.
Yana bir tuzoq: :not() yolg'iz yozilsa, juda keng ushlaydi. :not(p) — sahifadagi paragrafdan boshqa hamma narsa, html, head va body ham. Uni doim biror selektorga yopishtiring: main > :not(h1).
Tekshirib ko'ring:
footerdagi havolalardan tashqari hamma havolalarni qalin qiladigan selektor yozing.
Javob
a:not(footer a). O'qilishi: "havola, lekin footer ichidagi havola emas". :not(footer) a esa noto'g'ri — footer havolasining ham footer bo'lmagan otasi bor (body), shuning uchun u ham tanlanib qolardi.
5. :has() — "ichida X bor"
5.1 Yangi yo'nalish
Hozirgacha hamma selektorlar bir tomonga qaragan: ota → bola, oldingi → keyingi. :has() birinchi marta teskari yo'lni ochdi:
flowchart TD
D["div"] --> L["label"]
D --> S["span — yo'riqnoma"]
D --> I["input — :user-invalid"]
Y["label:has(~ :user-invalid)"] -.->|"tanlaydi"| L
X["div:has(> :user-invalid)"] -.->|"tanlaydi"| D
L ~~~ S ~~~ INimaga qarang: xato holati input da, lekin tanlanadigan elementlar — uning otasi div va undan oldin turgan label. Kombinatorlar bilan bunday qilib bo'lmasdi: ular faqat pastga va oldinga qaraydi. Shuning uchun dasturchilar :has() ni "ota selektori" (parent selector) deb ham atashadi.
:has() qavsi ichida selektor "shu elementdan boshlab" o'qiladi:
article:has(img)— ichida istalgan chuqurlikdaimgborarticle;article:has(> img)—imgbevosita bolasi bo'lganarticle;h2:has(+ p)— darhol keyinida paragraf turganh2;label:has(~ input)— keyingi qo'shnilari orasidainputborlabel.
Bu qavs ichidagi yozuv nisbiy selektor (relative selector) deb ataladi: u kombinator bilan boshlanishi mumkin, chunki uning boshlang'ich nuqtasi — :has() yopishgan element.
5.2 Rasmli karta
Asosiy selektorlar darsida va'da qilingan "ichida rasm bor karta":
<style>
.taom-karta {
border: 1px solid #5b6660;
padding: 0 12px;
margin: 8px 0;
}
.taom-karta:has(figure) {
border: 2px solid #2f6b3a;
background-color: #fffaf0;
}
</style>
<article class="taom-karta">
<figure>
<svg role="img" aria-label="Osh laganda"
width="80" height="50" viewBox="0 0 80 50">
<ellipse cx="40" cy="25" rx="38" ry="22" fill="#e8c07d"/>
</svg>
<figcaption>Choyxona oshi</figcaption>
</figure>
<h3>Osh — 35 000 so'm</h3>
</article>
<article class="taom-karta">
<h3>Lag'mon — 28 000 so'm</h3>
</article>Nimaga qarang: rasmli osh kartasi yashil qalin ramkada va qaymoq fonda, rasmsiz lag'mon kartasi — oddiy. HTML'da class qo'shilmadi: Rustam aka kartaga rasm qo'shsa, u o'zi "rasmli karta" bo'ladi. Rasm o'rnida biz inline SVG chizdik — figure ichida istalgan rasm bo'lishi mumkin (figure va figcaption).
Teskarisi ham oson: .taom-karta:not(:has(figure)) — rasmsiz kartalar. Mantiqiy pseudo-klasslar bir-birining ichida ishlaydi.
5.3 Forma: xato maydonning yorlig'i
Holat pseudo-klasslari darsidagi muammo: label maydondan oldin turadi, + esa orqaga qaramaydi. :has() bilan bu hal bo'ladi:
<style>
label:has(~ :user-invalid) {
color: #b4461a;
font-weight: bold;
}
input:user-invalid {
border: 2px solid #b4461a;
}
fieldset:has(:user-invalid) legend {
color: #b4461a;
}
</style>
<form action="https://example.com/bron" method="post">
<fieldset>
<legend>Siz haqingizda</legend>
<div>
<label for="ism">Ismingiz</label>
<input id="ism" name="ism" type="text" required>
</div>
<div>
<label for="telefon">Telefon raqamingiz</label>
<span id="telefon-yordam">Masalan: +998 90 000 00 00.</span>
<input id="telefon" name="telefon" type="tel" required
pattern="[0-9 +\-]{9,17}"
aria-describedby="telefon-yordam">
</div>
</fieldset>
<button type="submit">Stolni band qilish</button>
</form>Nimaga qarang: ismni yozib o'chiring va Tab bosing. Maydon ramkasi bilan birga uning yorlig'i ham qizg'ish va qalin bo'ladi. Guruh sarlavhasi "Siz haqingizda" ham qizaradi — mehmon qaysi guruhda xato borligini uzoqdan ko'radi. Ismni to'ldirsangiz, uchalasi ham o'z holiga qaytadi.
Telefon maydonida label va input orasida yo'riqnoma span turibdi. Shuning uchun + emas, ~ ishlatdik: "keyingi qo'shnilari orasida xato maydon bor label".
Holat pseudo-klasslari darsida form:invalid ni ko'rgan edik — u faqat "formada qayerdadir xato bor" deydi. :has() esa aynan qaysi guruh va qaysi yorliq ekanini ko'rsatadi.
5.4 Tanlangan variant va miqdor so'rovi
Radio tugmali qatorni butunligicha belgilash — ota div ni ichidagi :checked ga qarab tanlaymiz:
div:has(> :checked) {
background-color: #fffaf0;
}O'qilishi: "bevosita bolasi tanlangan tugma bo'lgan div". Holat pseudo-klasslari darsidagi "Qayerda o'tirasiz?" guruhini eslang: har radio tugma yorlig'i bilan birga alohida div da turardi. Endi "Ayvon" tanlansa, uning butun qatori — tugma ham, yorliq ham — qaymoq fonga kiradi. Buni pastdagi mashqlardan birida o'zingiz sinaysiz.
Tuzilma pseudo-klasslari darsidagi miqdor so'rovi ham ancha qisqaradi. "Kamida 5 qatorli ro'yxat":
ul:has(> li:nth-child(5)) {
font-size: 14px;
}O'qilishi: "beshinchi bolasi bor ul". Beshinchi qator bo'lsa — demak, qatorlar kamida beshta. Chrome'da tekshirdik: uch qatorli ro'yxat o'zgarmadi, besh qatorlisi kichraydi. Endi o'zgarish qatorlarga emas, ro'yxatning o'ziga beriladi.
5.5 Hammasi birga: xiralashadigan menyu
Mantiqiy pseudo-klasslar bir-birining ichida va holat pseudo-klasslari bilan birga ishlaydi. Mashhur usul: sichqoncha menyudagi bitta havola ustida tursa, qolganlari xiralashadi va ko'z tanlanganiga tushadi:
<style>
nav a {
color: #2f6b3a;
}
nav:has(a:hover) a:not(:hover) {
color: #5b6660;
}
</style>
<nav aria-label="Asosiy menyu">
<a href="menyu/">Menyu</a> ·
<a href="bron/">Stol band qilish</a> ·
<a href="aloqa/">Aloqa</a>
</nav>Nimaga qarang: havolalardan biriga sichqonchani olib boring — qolgan ikkitasi kulrang bo'ladi, tanlangan esa yashilligicha qoladi. Selektorni o'ngdan chapga o'qing: "sichqoncha ustida bo'lmagan havola, lekin faqat ichida hover qilingan havola bor nav da". Uch darsdagi uchta vosita — :hover, :not(), :has() — bitta qatorda birlashdi.
Tekshirib ko'ring:
h2:has(+ p)vah2 + pfarqi nima?
Javob
Ikkalasi bir xil juftlikni topadi, lekin boshqa elementni bo'yaydi. h2 + p — paragrafni tanlaydi (sarlavhadan keyingisini). h2:has(+ p) — sarlavhani tanlaydi (ostida paragraf turganini). Selektorning eng o'ng qismi hali ham "kimni bo'yaymiz"ni bildiradi, :has() esa unga shart qo'shadi.
6. :has() qoidalari va tezlik
6.1 Uchta cheklov
Chrome'da uchalasini tekshirdik — har birida brauzer butun qoidani tashladi:
- Ichma-ich bo'lmaydi.
:has(:has(img))— noto'g'ri. - Pseudo-element bo'lmaydi.
:has(::before)— noto'g'ri. - Kechirimli emas.
article:has(img, #1-taom)— bitta xato qism butun qoidani o'chirdi.
/* ❌ uchalasini ham brauzer tashlaydi */
article:has(:has(img)) { color: #b4461a; }
article:has(::before) { color: #b4461a; }
article:has(figure, #1-taom) { color: #b4461a; }6.2 Brauzerlarda va zaxira
:has() 2023-yil dekabridan hamma asosiy brauzerlarda ishlaydi. 2026-yil iyunidan esa Baseline "widely available" (Veb standartlari). Bugun uni bemalol ishlatsa bo'ladi. Lekin eski telefonni unutmang: :has() ni tanimaydigan brauzer butun qoidani tashlab ketadi — xuddi noto'g'ri selektor kabi.
Shuning uchun ikki qoida:
:has()li selektorni oddiy selektorlar bilan bitta vergulli ro'yxatga qo'shmang. Aks holda eski brauzerda oddiylari ham o'chib ketadi.:has()ni qo'shimcha bezak uchun ishlating. Asosiy ma'lumot — xato matni, narx — usiz ham ko'rinsin (Brauzer mosligi va progressive enhancement).
Brauzer biror selektorni biladimi-yo'qmi — CSS'ning o'zida tekshirish usuli ham bor. Uni Brauzer mosligi va @supports darsida o'rganamiz.
6.3 Tezlik
:has() brauzerdan ko'proq ish talab qiladi. Oddiy selektorda brauzer elementdan yuqoriga qarab tekshiradi. :has() da esa har o'zgarishda "ichida X paydo bo'ldimi?" deb qayta so'rashi kerak. MDN ikki maslahat beradi:
:has()nibody,:rootyoki*kabi juda umumiy elementga yopishtirmang.body:has(...)sahifadagi har qanday o'zgarishda butun hujjatni qayta tekshirtiradi. Aniq konteyner — kerakli elementlarni o'rab turgan eng yaqin ota — tanlang:.taom-karta:has(...),form:has(...).- Qavs ichida iloji boricha
>yoki+ishlating:article:has(> figure). Shunda brauzer butun ichki daraxtni emas, faqat bolalarni yoki qo'shnini ko'radi.
Oddiy sahifada farqni sezmaysiz. Minglab elementli katta ilovalarda esa bu maslahatlar muhim.
7. Ko'p uchraydigan xatolar
7.1 :not(X) Y — "X ichida bo'lmagan Y" emas
:not(nav) a hamma havolani tanlaydi. Tuzatish: a:not(nav a).
7.2 :not() yoki :has() ichida xato
Bitta noto'g'ri qism — butun qoida tashlanadi. Tuzatish: ichidagi har selektorni alohida tekshiring (DevTools'dagi Ctrl + F bilan — Asosiy selektorlar).
7.3 :has() li selektor vergulli ro'yxatda
h2, .taom-karta:has(figure) { ... } — eski brauzerda h2 ham bo'yalmaydi. Tuzatish: :has() li selektorga alohida qoida yozing.
7.4 body:has() hamma narsa uchun
Ishlaydi, lekin sekinroq. Tuzatish: eng yaqin aniq konteynerga yopishtiring.
7.5 :is() ichida pseudo-element
:is(p, ::before) — ::before qismi jimgina tashlanadi. Tuzatish: pseudo-elementni :is() dan tashqarida yozing: :is(h2, h3)::before.
7.6 Yolg'iz :not()
:not(p) { ... } — html va body ham tushadi. Tuzatish: :not() ni aniq selektorga yopishtiring.
8. Mashqlar
1-mashq (oson): Qisqartiring
Quyidagi qoidalarni :is() va :not() bilan qisqaroq yozing:
header a:focus-visible,
nav a:focus-visible,
footer a:focus-visible {
outline: 3px solid #1a5d1a;
}
main h2 strong,
main h3 strong {
color: #b4461a;
}Va yana bitta: oxirgisidan boshqa hamma li ga 1px solid #5b6660 pastki chiziq.
Yechim
:is(header, nav, footer) a:focus-visible {
outline: 3px solid #1a5d1a;
}
main :is(h2, h3) strong {
color: #b4461a;
}
li:not(:last-child) {
border-bottom: 1px solid #5b6660;
}Umumiy qismlar bir marta yozildi, farq qiladigani qavsga olindi. Uchinchi qoida o'tgan darsdagi ikki qoidani (li ga chiziq, li:last-child dan olib tashlash) bittaga birlashtirdi.
2-mashq (o'rta): Bron formasining "Qayerda o'tirasiz?" guruhi
«Bahor» formasidagi joy guruhi:
<fieldset>
<legend>Qayerda o'tirasiz?</legend>
<div>
<input id="joy-zal" name="joy" type="radio" value="zal" checked>
<label for="joy-zal">Umumiy zal</label>
</div>
<div>
<input id="joy-xona" name="joy" type="radio" value="xona"
aria-describedby="xona-yordam">
<label for="joy-xona">Alohida xona</label>
<span id="xona-yordam">8 kishidan boshlab.</span>
</div>
</fieldset>CSS yozing:
- Tanlangan variantning butun qatori —
#fffaf0fonda. - "Alohida xona" tanlanganda uning yo'riqnomasi — qizg'ish (
#b4461a) va qalin: mehmon shartni ko'rsin. - Tanlanmagan variantlarning yorlig'i — kulrang (
#5b6660).
Ishora: 1-band — div:has(> :checked). 2-band — yo'riqnoma tugmadan keyin turibdi, ~ yetadi. Yo'riqnomani id'si -yordam bilan tugashi bo'yicha toping (Atribut selektorlari). 3-band — :not() va :checked: yorliq tugmadan keyin turadi (+).
Yechim
<style>
div:has(> :checked) {
background-color: #fffaf0;
}
input:checked ~ span[id$="-yordam"] {
color: #b4461a;
font-weight: bold;
}
input:not(:checked) + label {
color: #5b6660;
}
</style>
<fieldset>
<legend>Qayerda o'tirasiz?</legend>
<div>
<input id="joy-zal" name="joy" type="radio" value="zal"
checked>
<label for="joy-zal">Umumiy zal</label>
</div>
<div>
<input id="joy-xona" name="joy" type="radio" value="xona"
aria-describedby="xona-yordam">
<label for="joy-xona">Alohida xona</label>
<span id="xona-yordam">8 kishidan boshlab.</span>
</div>
</fieldset>- "Alohida xona" ni bosing: fon ikkinchi qatorga ko'chadi, yo'riqnoma qizaradi, "Umumiy zal" yorlig'i esa kulrang bo'ladi.
- 2-band uchun
:has()kerak emas: tugma yo'riqnomadan oldin turibdi, oddiy~yetadi.:has()ni faqat haqiqatan orqaga yoki yuqoriga qarash kerak bo'lganda ishlating — u qimmatroq. - 2-band selektori faqat "xona" uchun yozilmadi: ertaga "Ayvon" ga ham yo'riqnoma qo'shilsa, u ham tanlanganda qizaradi.
3-mashq (qiyin): Stajyorning selektorlari
Stajyor menyu sahifasiga shunday CSS yozdi:
:not(footer) a { font-weight: bold; }
body:has(.achchiq) h1 { color: #b4461a; }
h2, .taom-karta:has(> figure) { border-bottom: 2px solid #2f6b3a; }
.taom-karta:has(figure, #1-rasm) { background-color: #fffaf0; }Jasur aka niyati: footer'dan boshqa havolalar qalin; menyuda achchiq taom bo'lsa, sarlavha qizg'ish; sarlavhalar va rasmli kartalar tagida yashil chiziq; rasmli kartalar — qaymoq fonda.
Har qatorning muammosini toping va tuzating.
Ishora: "Murakkab inkor va mashhur tuzoq" hamda ":has() qoidalari va tezlik" bo'limlarini qayta o'qing. Bitta qatorning muammosi zamonaviy brauzerda umuman ko'rinmaydi.
Yechim
a:not(footer a) { font-weight: bold; }
main:has(.achchiq) h1 { color: #b4461a; }
h2 { border-bottom: 2px solid #2f6b3a; }
.taom-karta:has(> figure) { border-bottom: 2px solid #2f6b3a; }
.taom-karta:has(figure) { background-color: #fffaf0; }:not(footer) a— footer havolalari ham tanlanadi: ularningbodyotasifooteremas. To'g'risi —a:not(footer a).body:has(.achchiq)— ishlaydi, lekin sahifadagi har o'zgarishda butun hujjat qayta tekshiriladi.main— yaqinroq va aniqroq konteyner.h2, .taom-karta:has(> figure)— zamonaviy Chrome'da ishlaydi. Lekin:has()ni bilmaydigan eski brauzer butun qoidani tashlaydi vah2chizig'i ham yo'qoladi. Ikki qoidaga ajratdik — bu muammo ko'zga ko'rinmaydigan qator edi.:has(figure, #1-rasm)—#1-rasmnoto'g'ri id selektori,:has()esa kechirimsiz. Butun qoida tashlandi. Keraksiz qismni olib tashladik.
4-mashq: Portfolio qadami — mantiqiy selektorlar
Portfolio HTML'iga tegmaymiz. asosiy.css ni yangilang:
- Birinchi darsdan beri turgan
h1, h2qoidasini:where()ga o'tkazing va ungah3ni ham qo'shing — bu sarlavhalar uchun "boshlang'ich" rang. - Holat pseudo-klasslari darsidagi
a:hoverfoni joriy sahifa havolasiga tushmasin. - Aloqa formasi: xato maydonning yorlig'i ham qizg'ish (
#b4461a) bo'lsin. Portfolio formasida har maydonpichida,label— maydondan oldin. - "Qaysi mavzuda?" guruhida mavzu tanlanmay qolgan bo'lsa (yuborishga urinishdan keyin), guruh sarlavhasi — qizg'ish.
Ishora: 2-band — :not([aria-current="page"]) ni a va :hover orasiga qo'ying. 3-band — label:has(~ :user-invalid). 4-band — fieldset:has(:user-invalid) legend.
Yechim
asosiy.css da h1, h2 qoidasi va a:hover qoidasi almashtiriladi, qolgani oxiriga qo'shiladi:
/* Sarlavhalar uchun boshlang'ich rang (og'irligi nol) */
:where(h1, h2, h3) {
color: #1f6f4a;
}
/* Hover — joriy sahifadan boshqa havolalarga */
a:not([aria-current="page"]):hover {
background-color: #e8f1ec;
}
/* Aloqa formasi: xato maydonning yorlig'i */
label:has(~ :user-invalid) {
color: #b4461a;
}
/* Tanlanmagan mavzu guruhi */
fieldset:has(:user-invalid) legend {
color: #b4461a;
}Aloqa formasining bir qismi:
<style>
body {
font-family: system-ui, sans-serif;
color: #1f2a24;
background-color: #f7faf8;
}
:where(h1, h2, h3) { color: #1f6f4a; }
input:user-invalid,
textarea:user-invalid {
border: 2px solid #b4461a;
}
label:has(~ :user-invalid) { color: #b4461a; }
fieldset:has(:user-invalid) legend { color: #b4461a; }
</style>
<h2>Xabar yuborish</h2>
<form action="https://example.com/aloqa" method="post">
<p>
<label for="ism">Ismingiz</label>
<input id="ism" name="ism" type="text"
autocomplete="name" required maxlength="60">
</p>
<fieldset>
<legend>Qaysi mavzuda?</legend>
<p>
<input id="mavzu-ish" name="mavzu" type="radio"
value="ish" required>
<label for="mavzu-ish">Ish taklifi</label>
</p>
<p>
<input id="mavzu-savol" name="mavzu" type="radio"
value="savol">
<label for="mavzu-savol">Savol</label>
</p>
</fieldset>
<button type="submit">Yuborish</button>
</form>Nozik joylar:
- Hech narsa to'ldirmasdan "Yuborish" ni bosing: ism yorlig'i va ramkasi qizaradi, "Qaysi mavzuda?" sarlavhasi ham. Mavzuni tanlasangiz, guruh sarlavhasi darhol qaytadi.
:where()ga o'tganda ko'rinish o'zgarmadi — sarlavhalar hali ham yashil. Farq keyinroq chiqadi: biror joyda sarlavhaga boshqa rang kerak bo'lsa, oddiyh2qoidasi ham uni bosib keta oladi.- Radio yorlig'i (
Ish taklifi) tugmadan keyin turadi, shuning uchunlabel:has(~ ...)unga tushmaydi. Bu yaxshi: guruh sarlavhasi yetarli. - Joriy sahifa havolasi endi hoverda o'zgarmaydi, lekin klaviatura fokusi halqasi unda qoladi — Bobur uchun u baribir havola.
9. Real ishda
- Formalar —
:has()ning eng ko'p ishlatiladigan joyi: xatoli guruhni, tanlangan kartani, to'ldirilgan qadamni belgilash. Ilgari buning uchun JavaScript yozilardi. - Komponent kutubxonalari o'z boshlang'ich stillarini
:where()bilan yozadi. Shunda siz ularni oddiy class bilan osongina o'zgartirasiz. Buni CSS reset darsida ko'rasiz. - Tailwind (kursda alohida o'rganamiz)
has-[...]:,not-[...]:yozuvlari vagroup/peerusullari aynan shu pseudo-klasslar ustiga qurilgan (Tailwind variantlari). - Intervyuda so'raladi: "CSS'da ota selektori bormi?" (ha,
:has()), ":is()va:where()farqi?", ":not(.a) .bva.b:not(.a .b)farqi?".
Xulosa
:is()— "ro'yxatdan istalgani": takrorni qisqartiradi va kechirimli — noto'g'ri qism butun qoidani buzmaydi.:where()—:is()ning o'zi, faqat og'irligi nol;:is()esa eng og'ir argumentining og'irligini oladi.:not()— inkor. "X ichida bo'lmagan Y" —Y:not(X Y),:not(X) Yemas. Kechirimsiz.:has()— ota va oldingi qo'shnini tanlash:article:has(figure),label:has(~ :user-invalid),div:has(> :checked).:has()ichma-ich bo'lmaydi, pseudo-element olmaydi, kechirimsiz; aniq konteynerga va>/+bilan yozing.
Keyingi dars: Pseudo-elementlar — ::before va ::after bilan HTML'da yo'q bezaklarni chizamiz: achchiqlik belgisi, majburiy maydon yulduzchasi, ro'yxat markeri.
Manbalar
- MDN: ":is()", ":where()", ":not()", ":has()" (tezlik bo'yicha tavsiyalar bilan) — developer.mozilla.org
- W3C: "Selectors Level 4" — mantiqiy pseudo-klasslar va nisbiy selektorlar — w3.org/TR/selectors-4
- web-features (Baseline ma'lumotlari): "has", "is", "where", "not" — github.com/web-platform-dx/web-features
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!