IlmHamroh
JavaScript Full-stack/5-qism. CSS asoslari va layout38/63-dars20 daqiqa
Mundarija (33)

CSS position: relative, absolute va containing block

Qisqacha: relative element o'z joyini saqlaydi va top/left bilan faqat o'zi suriladi. absolute element oqimdan butunlay chiqadi va eng yaqin "positsiyalangan" ota elementga — containing block'ga — nisbatan joylashadi. Shuning uchun burchakdagi belgining retsepti: kartaga position: relative, belgiga position: absolute; top: 0; right: 0.

Bu darsda

  • static, relative va absolute farqini natijada ko'rsatib bera olasiz.
  • Absolute element qaysi qutiga nisbatan joylashishini — containing block'ni — topasiz.
  • inset qisqa yozuvi bilan qoplama, belgi va markazlash naqshlarini yozasiz.
  • Skip link'ni faqat fokusda ko'rinadigan qilasiz va korinmas texnikasini ishlatasiz.

Oldin bilishingiz kerak: Normal oqim va formatting context, Pseudo-elementlar, Box model, Klaviatura va fokus, label.

1. Nega bu kerak?

HTML va CSS qismlarida besh marta "buni position darsida qilamiz" degan edik:

  • Pseudo-elementlar darsida qalampir belgisi taom nomidan keyin turdi. "Karta burchagiga joylashni position darsida o'rganamiz" degandik.
  • Overflow darsida "Yangi!" belgisini karta chegarasidan manfiy margin bilan chiqargan edik. Bu yamoq: belgi hamon oqimda va o'z qatorini egallaydi.
  • Klaviatura va fokus darsida skip link faqat Tab bosilganda ko'rinishi kerak edi.
  • label darsida korinmas class'i label'ni ko'zdan yashirib, ekran o'quvchiga qoldirishi kerak edi.
  • Forma xavfsizligi darsida honeypot bloki — asal-idish — "ekrandan chetga suriladi" degandik.

Beshalasining ildizi bitta: elementni normal oqimdan chiqarib, aniq bir joyga qo'yish. O'tgan darsda oqimni o'rgandik. Endi undan chiqishni o'rganamiz.

2. position qiymatlari

2.1 static — odatiy holat

Har elementning boshlang'ich qiymati — position: static. Element normal oqimda, o'z joyida. Bunday elementga top, right, bottom, left ta'sir qilmaydi — ular shunchaki e'tiborsiz qoladi.

Qolgan qiymatlar (relative, absolute, fixed, sticky) berilgan element positsiyalangan (positioned) deb ataladi. Bu so'z darsda ko'p takrorlanadi: "positsiyalangan" — static dan boshqa har qanday position.

2.2 relative — joy saqlanadi, o'zi suriladi

position: relative elementni o'z joyiga nisbatan siljitadi. Uchta kartani olamiz, o'rtadagisini suramiz:

html
<style>
  .taom-karta {
    width: 12rem;
    margin: 0 0 8px;
    padding: 4px 12px;
    border: 2px solid #2f6b3a;
    background-color: #fffaf0;
  }
  .taom-karta + .taom-karta {
    background-color: #d8ecd9;
  }
  .surilgan {
    position: relative;
    top: 1rem;
    left: 2rem;
  }
</style>
<article class="taom-karta"><h3>Osh</h3></article>
<article class="taom-karta surilgan"><h3>Manti</h3></article>
<article class="taom-karta"><h3>Lag'mon</h3></article>

Nimaga qarang: "Manti" kartasi pastga va o'ngga siljidi, "Lag'mon" ustiga chiqdi. Lekin "Lag'mon" joyidan qimirlamadi. Manti turgan eski joy bo'sh qoldi — oqim uni hali ham "band" deb hisoblaydi. Chrome'da o'lchadik: manti kartasi 16 piksel pastga va 32 piksel o'ngga surildi, lag'mon esa surilishdan oldingi joyida qoldi. surilgan — faqat shu misol uchun nom.

top: 1rem ni "tepadan 1rem uzoqlash" deb o'qing — element pastga tushadi. left: 2rem — "chapdan 2rem uzoqlash", ya'ni o'ngga. Manfiy qiymat teskari suradi.

relative ning siljitishi kamdan-kam kerak: ikonkani 1–2 piksel tushirish kabi mayda tuzatishlarda. Uning asosiy vazifasi boshqa — u elementni positsiyalangan qiladi, lekin joyidan qo'zg'atmaydi. Bu nega muhimligini «Containing block» bo'limida ko'rasiz.

2.3 absolute — oqimdan chiqadi

position: absolute element oqimdan butunlay chiqadi. Qo'shnilar uni ko'rmaydi — go'yo u umuman yo'q. Element esa top, right, bottom, left bilan aniq joyga qo'yiladi.

«Bahor» kartasiga "Yangi!" belgisini qo'yamiz — birinchi urinish:

html
<style>
  .taom-karta {
    width: 12rem;
    margin-top: 2rem;
    padding: 4px 12px;
    border: 2px solid #2f6b3a;
  }
  .taom-karta.yangi::before {
    content: "Yangi!";
    position: absolute;
    top: 0;
    right: 0;
    padding: 0 6px;
    background-color: #b4461a;
    color: #fffaf0;
  }
</style>
<article class="taom-karta yangi">
  <h3>Tandir go'sht</h3>
  <p>Har juma, tushlikda.</p>
</article>

Nimaga qarang: belgi kartaning burchagida emas — natija oynasining o'ng yuqori burchagiga "uchib" ketdi. Karta esa uni sezmadi: ichidagi matn joyida. Belgi oqimdan chiqdi, lekin qaysi qutining burchagiga borishini brauzer boshqacha tushundi.

Absolute element haqida yana uchta fakt:

  • Joy qoldirmaydi. Relative'dan farqi shu: eski joy bo'sh qolmaydi, qo'shnilar uni egallaydi.
  • Eni mazmunga qisqaradi. Blok element odatda butun enni oladi, absolute esa faqat o'z mazmunicha keng bo'ladi — xuddi fit-content (O'lchamlar).
  • Blokka aylanadi. Float kabi: absolute span ning hisoblangan display qiymati — block (Chrome'da tekshirdik). Unga width va padding to'liq ishlaydi.

Tekshirib ko'ring: Ikki paragraf orasidagi rasmga position: relative; top: 50px berildi. Keyingi paragraf joyidan siljiydimi? absolute bo'lsa-chi?

Javob

relative da yo'q: rasmning eski joyi band qoladi, rasm esa 50 piksel pastga tushib, keyingi paragraf ustiga chiqadi. absolute da ha: rasm oqimdan chiqadi, keyingi paragraf yuqoriga ko'tarilib, rasmning joyini egallaydi.

3. Containing block

3.1 Qoida

Belgi nega sahifa burchagiga ketdi? Chunki absolute element containing block ga nisbatan joylashadi. Containing block ("o'rab turuvchi quti") — elementning top, left va foizli o'lchamlari hisoblanadigan quti. Uni topish uchun brauzer elementning ajdodlari — otasi, bobosi va undan yuqoridagi o'rab turgan elementlar (Asosiy selektorlar darsidagi avlodning teskarisi) — bo'ylab yuradi:

flowchart TD
  A["position: absolute"] --> B["Otasiga qarang"]
  B --> C{"position<br/>static emasmi?"}
  C -->|Ha| D["Shu ajdod —<br/>containing block"]
  C -->|Yo'q| E["Uning otasiga o'ting"]
  E --> C
  E -->|Ajdod qolmadi| F["Boshlang'ich containing<br/>block: sahifa boshi"]

Nimaga qarang: brauzer yuqoriga, ota-bobolar zanjiri bo'ylab chiqadi va birinchi positsiyalangan ajdodda to'xtaydi. Hech kim topilmasa — boshlang'ich containing block: sahifaning eng boshidagi, oyna o'lchamidagi to'rtburchak. Bizning belgi shunday qilib natija oynasining burchagiga ketdi.

Xuddi pochta manzili kabi: "uchinchi eshik, chapdan" — qaysi binoning eshigi? Bino ko'rsatilmasa, xat butun shahar boshidan sanab ketiladi.

3.2 Retsept: ota — relative, bola — absolute

Endi relative bo'limidagi "relative elementni positsiyalangan qiladi, lekin joyidan qo'zg'atmaydi" degan gap kerak bo'ladi. Kartaga position: relative beramiz — va u belgi uchun "bino" bo'ladi:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
  }
  .taom-karta {
    position: relative;
    width: 14rem;
    margin: 1.5rem 0;
    padding: 4px 12px;
    border: 2px solid var(--rang-asosiy);
    background-color: var(--rang-fon);
  }
  .taom-karta.yangi::before {
    content: "Yangi!";
    position: absolute;
    top: -0.8em;
    left: 12px;
    padding: 0 6px;
    background-color: var(--rang-urgu);
    color: var(--rang-fon);
  }
  [data-achchiq="3"] h3::after {
    content: "🌶🌶🌶";
    content: "🌶🌶🌶" / "achchiqligi 3 dan 3";
    position: absolute;
    top: 8px;
    right: 8px;
  }
</style>
<article class="taom-karta yangi">
  <h3>Tandir go'sht</h3>
  <p>Har juma, tushlikda.</p>
</article>
<article class="taom-karta achchiq" data-achchiq="3">
  <h3>Lag'mon</h3>
  <p>Qo'lda cho'zilgan xamir.</p>
</article>

Nimaga qarang: "Yangi!" belgisi kartaning yuqori chegarasi ustida, chapdan 12 piksel ichkarida. Uchta qalampir lag'mon kartasining o'ng yuqori burchagida. Karta matni joyidan siljimadi. Pseudo-elementlar darsidagi va'da bajarildi.

Qalampirlar h3 ning ::after i, lekin ular sarlavhaga emas, kartaga nisbatan joylashdi. Sababi — qoida: h3 positsiyalanmagan, brauzer undan o'tib, kartada to'xtadi. Ikki content qatori Pseudo-elementlar darsidagidek: birinchisi — eski brauzerlar uchun zaxira, ikkinchisi Malikaga "achchiqligi 3 dan 3" deb o'qitadi.

Manfiy margin yamog'idan farqi: belgi endi hech qanday joy egallamaydi. U kartaning birinchi qatorini pastga surmaydi va kartaning tepa margin'iga aralashmaydi.

3.3 Qaysi chetdan o'lchanadi

Absolute element containing block'ning padding qutisi chetidan o'lchanadi — chegaraning ichki chetidan. top: 0; left: 0 — chegara ichidagi burchak, padding'ni hisobga olmasdan. Foizlar ham shu qutidan: top: 50% — padding qutisi bo'yining yarmi, width: 50% — enining yarmi.

Chrome'da o'lchadik: 2 piksellik chegarali kartadagi qalampir kartaning tashqi chetidan 10 piksel ichkarida turdi — 2 piksel chegara va right: 8px.

3.4 Containing block'ni yana nima yaratadi

position dan boshqa ba'zi xususiyatlar ham ajdodni absolute bolalari uchun "bino"ga aylantiradi. Eng ko'p uchraydiganlari:

  • transform — elementni siljitish yoki burish (2D transformlar);
  • filter — xiralash va boshqa effektlar (Filterlar);
  • contain: paint yoki contain: layout.

Ular hali o'tilmagan — hozir faqat eslab qoling: belgi kutilmagan joyga borsa, DevTools'da ajdodlarda shu xususiyatlar bormi, tekshiring. position: fixed uchun bu qoida ancha jiddiy tuzoqqa aylanadi — keyingi darsda.

Tekshirib ko'ring: section (position: relative) ichida article (odatiy), uning ichida span (position: absolute; bottom: 0). span kimning pastki chetiga yopishadi?

Javob

section ning. article ning position qiymati — static, u containing block bo'lmaydi. Brauzer undan o'tib, birinchi positsiyalangan ajdod — section da to'xtaydi. span ni article ning pastiga qo'yish uchun article ga position: relative bering.

4. inset va naqshlar

4.1 inset qisqa yozuvi

To'rtta top, right, bottom, left ni bitta inset xususiyati birlashtiradi. Qiymatlar soni margin dagidek ishlaydi — soat mili bo'yicha (CSS nima):

Yozuv Ma'nosi
inset: 0; To'rt tomon ham 0
inset: 8px 16px; Tepa va past 8, o'ng va chap 16
inset: 0 0 auto auto; Tepa va o'ng 0 — o'ng yuqori burchak
inset: auto; Hammasi auto — odatiy

Baseline ma'lumotlariga ko'ra inset 2021-yil aprelidan hamma asosiy brauzerda bor va keng tarqalgan. Eski kodda uning o'rnida to'rt qator uchratasiz — ma'nosi bir xil.

4.2 inset: 0 — to'liq qoplama

Qarama-qarshi ikki tomon ham berilsa, absolute element ular orasiga cho'ziladi. inset: 0 — to'rt tomon ham 0: element containing block'ni butunlay qoplaydi. Bu qoplama (overlay) naqshi.

Taom tugaganda Jasur aka kartani o'chirmasdan, uning ustiga xira parda va "Tugadi" muhrini qo'yishni xohlaydi:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
  }
  .taom-karta {
    position: relative;
    width: 14rem;
    padding: 4px 12px;
    border: 2px solid var(--rang-asosiy);
    background-color: var(--rang-fon);
  }
  .taom-karta.tugadi::before {
    content: "";
    position: absolute;
    inset: 0;
    background-color: color-mix(in srgb, var(--rang-fon) 70%,
      transparent);
  }
  .taom-karta.tugadi::after {
    content: "Tugadi";
    position: absolute;
    inset: 0;
    width: fit-content;
    height: fit-content;
    margin: auto;
    padding: 2px 10px;
    border: 3px solid var(--rang-urgu);
    background-color: var(--rang-fon);
    color: var(--rang-urgu);
    font-weight: bold;
  }
</style>
<article class="taom-karta tugadi">
  <h3>Norin</h3>
  <p>Ot go'shti va qo'lda kesilgan xamir.</p>
</article>

Nimaga qarang: karta ustini qaymoq rangli yarim shaffof parda qopladi — matn xiralashdi, lekin o'qiladi. "Tugadi" muhri kartaning roppa-rosa o'rtasida.

  • Parda (::before) — content: "" (bo'sh, lekin kerak) va inset: 0. U kartaning padding qutisini to'liq qoplaydi. Rang Ranglar 3 darsidagi color-mix() bilan: fonning 70 foizi, qolgani shaffof.
  • Muhr (::after) — ham inset: 0, lekin o'lchami fit-content. Brauzer uni to'rt tomondan 0 ga qo'yolmaydi: element kichikroq. Shunda margin: auto bo'sh joyni teng bo'ladi — element ikkala o'qda markazga keladi. Chrome'da o'lchadik: muhrning chap va o'ng tomonidagi bo'shliq, tepa va pastki bo'shliq teng.
  • Muhr pardadan ustda, chunki ::after HTML tartibida keyin keladi. Qatlamlar tartibini z-index darsida to'liq ochamiz.

tugadi — «Bahor»ning kanonik modifikatori (Gradientlar darsida chiziqli fon bilan ko'rgan edik). "Tugadi" so'zi pseudo-elementda, lekin Malika uni baribir eshitadi: content matni accessibility daraxtiga tushadi (Pseudo-elementlar).

4.3 Cho'zish va markazlash — ikki xil yo'l

inset bilan cho'zilish faqat width/height berilmaganda ishlaydi. Qoidani eslab qoling:

  • O'lcham yo'q + qarama-qarshi tomonlar berilgan → element cho'ziladi (parda).
  • O'lcham bor + qarama-qarshi tomonlar + margin: auto → element markazga keladi (muhr).

Markazlashning boshqa usullari — Flexbox va Grid bilan — Flex naqshlari darsida hammasi bir joyda.

Tekshirib ko'ring: .parda { position: absolute; inset: 0; } yozildi, lekin parda karta ustida emas, butun natija oynasini qopladi. Nima unutilgan?

Javob

Kartaning position: relative i. Usiz kartadan yuqorida positsiyalangan ajdod yo'q, containing block — sahifa boshidagi oyna o'lchamidagi to'rtburchak. inset: 0 pardani aynan o'shaga yoydi.

5. Ko'zdan yashirish, lekin sahifada qoldirish

5.1 korinmas texnikasi

display va yashirish darsidagi besh usulning hech biri bitta vazifaga to'g'ri kelmadi: matn ko'zga ko'rinmasin, lekin ekran o'quvchi uni o'qisin. Masalan, «Bahor» menyusida "Batafsil" havolalari ko'p. Ko'radigan odam qaysi taomniki ekanini kartadan biladi. Malika esa havolalar ro'yxatida o'nta bir xil "Batafsil" ni eshitadi (Kontent accessibility'si).

Yechim — havola ichiga yashirin qism qo'shish:

html
<a href="menyu/osh/">Batafsil<span class="korinmas"> (osh)</span></a>

korinmas class'ining CSS'i — The A11Y Project va Scott O'Hara'ning "Inclusively Hidden" maqolasidagi mashhur parchaning zamonaviy shakli:

css
.korinmas {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

Har qator nega kerak:

  • position: absolute — element oqimdan chiqadi va joy egallamaydi. Qo'shni so'zlar surilmaydi.
  • width: 1px; height: 1px — quti bir nuqtaga qisqaradi. 0 emas: manbalarga ko'ra, o'lchami nol elementni ba'zi ekran o'quvchilar o'tkazib yuboradi.
  • overflow: hidden — 1 piksellik qutidan chiqqan matn kesiladi (Overflow).
  • clip-path: inset(50%) — qutini har tomondan yarmigacha kesadi, ya'ni ko'rinadigan qismi qolmaydi. clip-path ni clip-path va maskalar darsida to'liq o'rganamiz.
  • white-space: nowrap — matn bitta qatorda qoladi. Tor qutida so'zlar har biri alohida qatorga tushadi, ba'zi ekran o'quvchilar esa ularni bo'sh joysiz, qo'shib o'qib yuboradi.

Chrome'ning accessibility daraxtida tekshirdik: havolaning nomi — "Batafsil (osh)". Ekranda esa faqat "Batafsil". Qavs oldidagi bo'sh joy ataylab: absolute span ni brauzer alohida bo'lak deb hisoblaydi. Batafsil<span>: osh</span> ko'rinishida Chrome nomni "Batafsil : osh" qilib, ikki nuqta oldiga bo'sh joy qo'shdi. Qavsli variantda nom toza chiqadi.

Maslahat: Internetda bu parchaning clip: rect(0 0 0 0) qatori bor shaklini ham ko'p uchratasiz — A11Y Project'da ham u hali turibdi. Bu eskirgan xususiyat, u juda eski brauzerlar uchun zaxira. Uning o'rnini bosgan clip-path esa Baseline ma'lumotiga ko'ra 2021-yil yanvaridan beri hamma asosiy brauzerda bor, shuning uchun biz clip siz yozdik. Texnikaning to'liq nazariyasi — qachon kerak, qachon aria-label yaxshiroq — CSS'da accessibility darsida.

Klaviatura va fokus darsida skip link'ni left: -9999px bilan chetga surgan edik. U ishlaydi, lekin bitta yashirin tuzog'i bor. Chrome'da tekshirdik: dir="rtl" li (arabcha) sahifada chapga surilgan element gorizontal skroll yaratdi — sahifa eni 800 dan 10 799 pikselga cho'zildi. O'ngdan chapga yoziladigan sahifada chap tomon "oldinga" hisoblanadi va unga surib borsa bo'ladi. Yozuv yo'nalishlarini Mantiqiy xususiyatlar darsida ko'ramiz.

Yaxshiroq yo'l — o'sha korinmas texnikasi, faqat fokusda bekor qilinadi:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-fon: #fffaf0;
  }
  .korinmas,
  .otish:not(:focus) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .otish:focus {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    padding: 0.5rem 1rem;
    background-color: var(--rang-asosiy);
    color: var(--rang-fon);
  }
</style>
<a class="otish" href="#asosiy">Asosiy kontentga o'tish</a>
<header>
  <p><strong>Choyxona «Bahor»</strong></p>
  <nav aria-label="Asosiy menyu">
    <a href="menyu/">Menyu</a> · <a href="bron/">Bron</a>
  </nav>
</header>
<main id="asosiy">
  <h1>Xush kelibsiz!</h1>
</main>

Nimaga qarang: sahifada skip link ko'rinmaydi. Natija ichiga bir marta bosing va Tab tugmasini bosing — chap yuqori burchakda yashil "Asosiy kontentga o'tish" tugmasi chiqadi. Yana Tab bossangiz, fokus "Menyu" ga o'tadi va tugma yana yashirinadi. Enter bilan main ga sakrashni o'z faylingizda, Live Server'da sinab ko'ring.

  • .otish:not(:focus) — "fokusda bo'lmagan skip link". Mantiqiy pseudo-klasslar darsidagi :not(). Fokus kelishi bilan bu selektor ishlamay qoladi va yashirish qoidalari bekor bo'ladi.
  • .otish:focus — endi havola absolute: sahifani surmaydi, sarlavha ustida turadi. :focus-visible emas, :focus: skip link'ni sichqoncha bilan bosib bo'lmaydi, u faqat klaviaturadan fokus oladi.
  • Bitta qoida ikki class'ga xizmat qiladi: korinmas doim yashiradi, otish — fokusdan tashqarida.

Sarlavha ham positsiyalangan bo'lsa (masalan, keyingi darsdagi yopishqoq sarlavha), tugma uning ostida qolishi mumkin. Buni z-index hal qiladi.

5.3 Honeypot — ekrandan chetga

Forma xavfsizligi darsidagi asal-idish bloki botlar uchun tuzoq. Uni display: none bilan yashirib bo'lmaydi: ehtiyotkor botlar yashirin maydonni taniydi va to'ldirmaydi. Blok sahifada qoladi, faqat ko'rinadigan maydondan tashqariga suriladi:

css
.asal-idish {
  position: absolute;
  left: -100vw;
}

left: -100vw — oynaning butun enicha chapga. Blokdagi label "Bu maydonni bo'sh qoldiring" deydi: agar Malikaning ekran o'quvchisi unga duch kelsa, u nima qilishni biladi. tabindex="-1" esa Tab ni maydonga olib kirmaydi — bu HTML'da allaqachon bor. «Bahor» — chapdan o'ngga yoziladigan sayt, shuning uchun skip link bo'limidagi o'ngdan chapga yozuv tuzog'i bu yerda xavf emas. Uni yo'nalishga bog'liq bo'lmagan qilishni Mantiqiy xususiyatlar darsida ko'ramiz.

Tekshirib ko'ring: Nega korinmas da display: none yoki width: 0 ishlatilmaydi?

Javob

display: none elementni accessibility daraxtidan ham olib tashlaydi — ekran o'quvchi uni o'qimaydi (display va yashirish). Nol o'lchamli elementni esa manbalarga ko'ra ba'zi ekran o'quvchilar o'tkazib yuboradi. 1×1 piksel, overflow: hidden va clip-path — ko'zga yo'q, lekin brauzer va ekran o'quvchi uchun to'liq matn.

6. Ko'p uchraydigan xatolar

6.1 Ota relative emas

Belgi sahifa burchagiga yoki boshqa kartaga "uchib" ketdi. Tuzatish: belgi kimga nisbatan turishi kerak bo'lsa, o'shanga position: relative.

6.2 Karta overflow: hidden — belgi kesildi

Chegaradan tepaga chiqarilgan "Yangi!" belgisining yarmi yo'q. overflow absolute bolalarni ham kesadi, agar karta ularning containing block'i bo'lsa. Tuzatish: overflow ni olib tashlang; margin yoki float'ni ushlash kerak bo'lsa — display: flow-root (Normal oqim).

6.3 Layout'ni absolute bilan qurish

Ustunlar, kartalar to'ri — hammasi absolute va piksellar bilan. Matn uzaysa yoki ekran toraysa, hammasi bir-birining ustiga chiqadi: oqimdan chiqqan elementlar bir-birini "ko'rmaydi". Tuzatish: layout — Flexbox va Grid. absolute — faqat bezak va qatlamlar uchun.

6.4 width: 100% + padding — chetdan chiqdi

Parda width: 100%; height: 100%; padding: 1rem bilan yozildi va karta chetidan chiqib ketdi. Tuzatish: inset: 0 — padding bilan ham containing block chegarasida qoladi. Yoki box-sizing: border-box.

6.5 static elementga top

top: 10px yozildi — hech narsa o'zgarmadi. Tuzatish: position qo'shing; faqat siljitish kerak bo'lsa — relative.

7. Mashqlar

Mashqlarni kurs/mashqlar/05/ papkasida bajaring.

1-mashq (oson): Containing block qaysi?

html
<section class="menyu">
  <article class="taom-karta">
    <h3>Osh <span class="belgi">Yangi!</span></h3>
  </article>
</section>

.belgi { position: absolute; top: 0; }. Har holatda span qaysi elementning tepasiga yopishadi (element nomini yozing):

  1. Hech kimda position yo'q — (sahifa boshi)
  2. .menyu { position: relative; } —
  3. .menyu va .taom-karta ikkalasi ham relative —
  4. Faqat h3 { position: relative; } —

Ishora: «Containing block» diagrammasi — brauzer yuqoriga chiqib, birinchi positsiyalangan ajdodda to'xtaydi.

Yechim
  1. Hech kim positsiyalanmagan — boshlang'ich containing block, ya'ni sahifaning boshi (html ning joyi).
  2. section — yagona positsiyalangan ajdod.
  3. article — u yaqinroq. Brauzer birinchisida to'xtaydi.
  4. h3 — to'g'ridan-to'g'ri ota. class="menyu" va belgi — shu mashq uchun nomlar.

2-mashq (o'rta): Achchiq belgisi va "Yangi!" bir kartada

«Bahor» menyusida yangi va achchiq taom bor:

html
<article class="taom-karta yangi achchiq" data-achchiq="2">
  <h3 class="taom-nomi">Qovurma lag'mon</h3>
  <p><span class="narx">32 000 so'm</span></p>
</article>

asosiy.css ga yozing:

  1. "Yangi!" belgisi kartaning chap yuqori burchagida, chegaraning ustida.
  2. Ikkita qalampir (data-achchiq="2") o'ng pastki burchakda, chetlardan 8px ichkarida.
  3. Belgilar karta matnini surmasin.

Ishora: «Retsept: ota — relative, bola — absolute» natijasi. Pastki burchak — bottom va right. Qalampir uchun Pseudo-elementlar darsidagi ikki qatorli content.

Yechim
html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
  }
  .taom-karta {
    position: relative;
    width: 14rem;
    margin-top: 1.5rem;
    padding: 4px 12px;
    border: 2px solid var(--rang-asosiy);
    background-color: var(--rang-fon);
  }
  .taom-karta.yangi::before {
    content: "Yangi!";
    position: absolute;
    top: -0.8em;
    left: 12px;
    padding: 0 6px;
    background-color: var(--rang-urgu);
    color: var(--rang-fon);
  }
  [data-achchiq="2"] .taom-nomi::after {
    content: "🌶🌶";
    content: "🌶🌶" / "achchiqligi 2 dan 3";
    position: absolute;
    right: 8px;
    bottom: 8px;
  }
  .narx {
    color: var(--rang-urgu);
    font-weight: bold;
  }
</style>
<article class="taom-karta yangi achchiq" data-achchiq="2">
  <h3 class="taom-nomi">Qovurma lag'mon</h3>
  <p><span class="narx">32 000 so'm</span></p>
</article>
  • Karta — relative: ikkala belgining containing block'i.
  • Qalampirlar sarlavhaning ::after i, lekin bottom: 8px ularni kartaning pastki chetidan o'lchaydi, sarlavhanikidan emas — h3 positsiyalanmagan.
  • Belgilar oqimdan chiqqan: sarlavha va narx o'z joyida.

3-mashq (qiyin): Nega hammasi buzildi?

Stajyor «Bahor» bron formasi ustiga "Hozir bron yopiq" pardasini qo'ydi:

css
form {
  overflow: hidden;
}
.parda {
  position: absolute;
  width: 100%;
  height: 100%;
  padding: 1rem;
  background-color: #fffaf0cc;
}
.parda strong {
  position: absolute;
  top: 50%;
  left: 50%;
}

div class="parda" — form ning birinchi bolasi, ichida strong bilan "Hozir bron yopiq" matni. Shikoyatlar:

  • (a) Parda formani emas, butun sahifani qopladi.
  • (b) Tuzatilgandan keyin ham parda o'ng va pastdan chiqib turibdi.
  • (c) "Hozir bron yopiq" markazda emas — o'ngroqda va pastroqda.

Sabablarini toping va tuzating.

Ishora: «Containing block» qoidasi, «inset: 0 — to'liq qoplama» va «width: 100% + padding» xatosi. (c) uchun top: 50% elementning qaysi nuqtasini markazga qo'yishini o'ylang.

Yechim
  • (a) form positsiyalanmagan — containing block sahifa boshi. overflow: hidden bu yerda yordam bermaydi: u pardani faqat form uning containing block'i bo'lgandagina kesadi.
  • (b) width: 100% + padding — padding enning ustiga qo'shiladi (box-sizing).
  • (c) top: 50%; left: 50% matnning chap yuqori burchagini markazga qo'yadi, markazini emas.
css
form {
  position: relative;
}
.parda {
  position: absolute;
  inset: 0;
  background-color: #fffaf0cc;
}
.parda strong {
  position: absolute;
  inset: 0;
  width: fit-content;
  height: fit-content;
  margin: auto;
}
  • overflow: hidden olib tashlandi — endi kesiladigan narsa yo'q. Formaning fokus halqalari ham kesilmaydi.
  • inset: 0 pardani padding'siz ham, padding bilan ham formaning chegarasida ushlaydi.
  • Matn — "Tugadi" muhri kabi: fit-content + margin: auto. class="parda" — shu mashq uchun nom.
  • Yana bitta muhim gap: parda formani faqat ko'zdan yopadi. Bobur Tab bilan maydonlarga baribir kiradi. Formani haqiqatan to'xtatish — inert atributi (display va yashirish).

Yakuniy loyiha darsida skip link hamma sahifada ko'rinib turardi: "CSS qismida uni faqat fokusda ko'rinadigan qilamiz" degan edik. Shu va'dani bajaramiz.

  1. Skip link bor beshta sahifada (index.html, haqimda/, loyihalar/, aloqa/, loyihalar/bahor/) <a href="#asosiy"> ga class="otish" qo'shing. 404.html da skip link yo'q — unga tegmang.
  2. asosiy.css ga korinmas va otish qoidalarini yozing. Fokusdagi skip link — brend rangida, chap yuqori burchakda.
  3. loyihalar/index.html da ikkita "Saytni ochish" havolasi bor. Ekran o'quvchi uchun ularni farqlang: qaysi loyihaning sayti ekanini korinmas bilan qo'shing.
  4. Tekshiring: sahifani oching, Tab bosing — skip link chiqadi; yana Tab — yashirinadi. npm run check — html-validate class nomini kebab-case deb qabul qilsin.

Ishora: «korinmas texnikasi» va «Skip link» bo'limlari. Portfolio ranglari — --rang-asosiy va --rang-fon.

Yechim

Har sahifada:

html
<a class="otish" href="#asosiy">Asosiy kontentga o'tish</a>

loyihalar/index.html da:

html
<a href="https://example.com/bahor/">Saytni ochish<span
  class="korinmas"> (Choyxona «Bahor»)</span></a>
html
<a href="https://example.com/blog/">Saytni ochish<span
  class="korinmas"> (Semantik blog maqolasi)</span></a>

asosiy.css:

css
/* Ko'zdan yashirin, ekran o'quvchiga eshitiladi */
.korinmas,
.otish:not(:focus) {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.otish:focus {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  padding: 0.5rem 1rem;
  background-color: var(--rang-asosiy);
  color: var(--rang-fon);
}
  • span havolaning ichida: "Saytni ochish" va "(Choyxona «Bahor»)" bitta nom bo'lib o'qiladi. Chrome'ning accessibility daraxtida havolaning nomi — "Saytni ochish (Choyxona «Bahor»)".
  • Skip link fokusda portfolio'ning oq-yashil ranglarida: --rang-fon --rang-asosiy ustida 5.8:1 dan yuqori kontrast.
  • Qator bo'linishi <span va class orasida — atributlar orasidagi bo'sh joy, u matnga qo'shilmaydi. Nomdagi bo'sh joy — qavs oldidagisi, u span ning ichida.
  • 404.html ga hech narsa qo'shilmadi: unda skip link yo'q, main esa id siz (Viewport birliklari darsidagi main:not([id]) shunga tayanadi).
  • Lighthouse Accessibility'ni qayta o'tkazing: ball pasaymasin, yangi qizil qator chiqmasin.

8. Real ishda

  • Belgilar va nishonlar — "Yangi", "−20%", xabarlar soni ikonka burchagida: hammasi relative ota + absolute bola.
  • Kartadagi qoplama — rasm ustidagi qora gradient va unga yozilgan sarlavha, "Tugadi" yoki "Tez orada" pardalari — inset: 0.
  • Skip link va sr-only — deyarli har bir jiddiy saytda. Tailwind'da (kursda alohida o'rganamiz) bu texnika sr-only class'i, Bootstrap'da — visually-hidden.
  • Tooltip va ochiladigan menyular ham absolute bilan. Ularning ekranga sig'ishini bugun maxsus vosita boshqaradi — Anchor positioning.
  • Intervyuda so'raladi: "relative va absolute farqi?", "Absolute element nimaga nisbatan joylashadi?", "Elementni absolute bilan qanday markazlaysiz?", "Screen reader uchun matnni qanday yashirasiz?".

Xulosa

  • static — odatiy, top/left ishlamaydi. relative — joyi saqlanadi, o'zi suriladi. absolute — oqimdan chiqadi, joy qoldirmaydi.
  • Absolute element containing block'ga nisbatan joylashadi: birinchi positsiyalangan ajdod, bo'lmasa — sahifa boshi. transform va filter ham containing block yaratadi.
  • Retsept: ota — position: relative, bola — position: absolute. O'lchov ota chegarasining ichki chetidan.
  • inset: 0 — to'liq qoplama; o'lcham + inset: 0 + margin: auto — markazlash.
  • korinmas: absolute + 1×1 piksel + overflow: hidden + clip-path: inset(50%) + nowrap. Skip link — xuddi shu, :not(:focus) bilan.

Keyingi dars: position: fixed va sticky — va ularning tuzoqlari — ekranga yopishgan tugma, skrollda qotib qoladigan sarlavha va ularni jimgina buzadigan ota xususiyatlari.

Manbalar

  • MDN: "position", "inset", "Containing block", "clip-path" — developer.mozilla.org
  • W3C: "CSS Positioned Layout Module Level 3" — w3.org/TR/css-position-3
  • The A11Y Project: "How-to: Hide content" — a11yproject.com/posts/how-to-hide-content
  • Scott O'Hara: "Inclusively Hidden" — scottohara.me/blog/2017/04/14/inclusively-hidden.html
  • web-features (Baseline ma'lumotlari): "inset" (logical-properties), "clip-path", "absolute-positioning" — github.com/web-platform-dx/web-features
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS position: relative, absolute va containing block — IlmHamroh