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

CSS karusel va gorizontal skroll lentasi: scroll-snap, ::scroll-button va ::scroll-marker

Qisqacha: Karusel — bir qatorda turgan va yon tomonga suriladigan kartalar yoki slaydlar. Uning asosi JavaScript emas, oddiy gorizontal skroll: overflow-x: auto + scroll-snap-type: x mandatory + kartalarga scroll-snap-align. Nuqtalarni hamma brauzerda #havola lar bilan, oldinga-orqaga tugmalarini va nuqtalarni esa Chrome'da ::scroll-button() va ::scroll-marker bilan CSS o'zi yaratadi (Baseline emas — boshqa brauzerda oddiy lenta qoladi). Avto-aylanish — JavaScript ishi va u deyarli har doim yomon g'oya.

Bu darsda

  • Kartalar lentasini "keyingisi chetdan ko'rinib turadigan" qilib quring va uni telefonda tekshirasiz.
  • Skrollbarni yashirish qachon xavfli ekanini va o'rniga nima qilishni bilasiz.
  • Hamma brauzerda ishlaydigan nuqtali navigatsiyani #havola lar bilan yozasiz.
  • Chrome'da ::scroll-button() va ::scroll-marker bilan to'liq CSS karusel quring va boshqa brauzerlar uchun zaxira qoldirasiz.
  • Avto-aylanish, prefers-reduced-motion va Swiper/Embla kabi kutubxonalar haqida to'g'ri qaror qabul qila olasiz.

Oldin bilishingiz kerak: Skroll xulqi va scroll-snap, prefers-reduced-motion va harakat etikasi, Yangi paydo bo'layotgan CSS, Anchor positioning, ARIA patternlari.

1. Nega bu kerak?

Jasur aka bosh sahifada "Bugungi takliflar"ni ko'rsatmoqchi: osh, lag'mon, manti, somsa, sho'rva. Beshta karta. Telefonda ular ustma-ust tursa, mehmon asosiy ma'lumotgacha uzoq aylantiradi. Bir qatorga siqilsa — har biri gugurt qutisidek kichik.

Yechim — gorizontal lenta: kartalar bir qatorda, ekran enidan chiqib ketadi, mehmon ularni barmog'i bilan yon tomonga suradi. Instagram'dagi "hikoyalar", Telegram'dagi stikerlar paneli, do'kon ilovasidagi "Sizga yoqishi mumkin" — hammasi shunday.

Karusel (carousel) — shu lentaning "boshqariladigan" turi: oldinga-orqaga tugmalari va "nechanchi slayd" nuqtalari bor. Nomi bayramdagi aylanadigan otchalardan olingan: bir ot o'tadi, keyingisi keladi.

Lekin avval bir ogohlantirish. ARIA patternlari darsida karuselni "eng muammoli vidjetlardan biri" degan edik. Sabablari:

  • ko'p foydalanuvchi ikkinchi slaydgacha ham yetib bormaydi — ular ichidagi ma'lumotni ko'rmaydi;
  • avtomatik aylanadigan karusel o'qib ulgurmasdan matnni olib ketadi;
  • telefonda "surish" va sahifani pastga aylantirish bir-biriga xalaqit beradi.

Shuning uchun dars ikki qismdan iborat: avval nima qilish — to'g'ri lenta. Keyin nima qilmaslik — avto-aylanish va yashirin navigatsiya.

2. Asos: gorizontal lenta

2.1 "Keyingisi ko'rinib tursin"

Skroll xulqi va scroll-snap darsida magnitli lentani qurgan edik. Endi uni haqiqiy komponentga aylantiramiz: kartalar ichida havola, lenta chetlari sahifa ustuniga tekis, telefon va kompyuterda to'g'ri o'lcham.

html
<style>
  body { margin: 0; font-family: system-ui, sans-serif; }
  h2 { margin: 16px; }
  .lenta {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: min(75%, 16rem);
    gap: 12px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 16px;
    padding: 0 16px 12px;
    margin: 0;
    list-style: none;
  }
  .lenta li {
    display: grid;
    scroll-snap-align: start;
  }
  .taom-karta {
    padding: 16px;
    border: 2px solid #2f6b3a;
    border-radius: 12px;
    background: #fffaf0;
  }
  .taom-karta h3 { margin: 0 0 4px; }
  .taom-karta p { margin: 0 0 8px; }
  .narx { color: #b4461a; font-weight: bold; }
  .taom-karta a { color: #2f6b3a; }
</style>
<h2>Bugungi takliflar</h2>
<ul class="lenta" aria-label="Bugungi takliflar">
  <li><article class="taom-karta"><h3>Osh</h3>
    <p class="narx">35 000 so'm</p>
    <a href="menyu/#osh">Batafsil</a></article></li>
  <li><article class="taom-karta"><h3>Lag'mon</h3>
    <p class="narx">28 000 so'm</p>
    <a href="menyu/#lagmon">Batafsil</a></article></li>
  <li><article class="taom-karta"><h3>Manti</h3>
    <p class="narx">30 000 so'm</p>
    <a href="menyu/#manti">Batafsil</a></article></li>
  <li><article class="taom-karta"><h3>Somsa</h3>
    <p class="narx">8 000 so'm</p>
    <a href="menyu/#somsa">Batafsil</a></article></li>
  <li><article class="taom-karta"><h3>Sho'rva</h3>
    <p class="narx">25 000 so'm</p>
    <a href="menyu/#shorva">Batafsil</a></article></li>
</ul>

Nimaga qarang: telefon enida (360) birinchi karta ekranning to'rtdan uchini egallaydi, o'ngda ikkinchisining bir bo'lagi ko'rinib turibdi. Bu — "yana bor, suring" degan ishora. Katta ekranda (768 va 1280) kartalar 16rem (256 piksel) enli: 1280 da to'rttasi to'liq ko'rinadi, beshinchisi chetdan chiqib turadi. Surganda har karta sarlavhaning chap cheti bilan bir chiziqqa "yopishadi".

Kodni o'qiymiz:

  • grid-auto-flow: column — har yangi band yangi ustunga tushadi, bitta qatorda (Grid'da joylashtirish). grid-auto-columns: min(75%, 16rem) — telefonda ekranning 75%, kattada 16rem. Flex bilan ham bo'ladi, lekin grid'da flex-shrink tuzog'i yo'q (Skroll xulqi darsidagi "kartalar siqilib qoldi" xatosi).
  • padding va scroll-padding-inline bir xil — 16px. Padding birinchi kartani sahifa chetidan uzoqlashtiradi. Scroll-padding esa snap nuqtasini ham o'sha 16 pikselga suradi. Ikkinchisisiz karta ekran chetiga yopishardi.
  • overscroll-behavior-x: contain — lenta oxiriga yetganda surish sahifaga "o'tib ketmaydi": telefonda brauzerning "orqaga" imo-ishorasi tasodifan ishlamaydi. Rasman Baseline emas (Safari'da qisman), lekin Skroll xulqi darsida ko'rganimizdek, lentadagi asosiy holat hamma joyda ishlaydi.
  • li ga display: grid — ichidagi karta li ning butun balandligini egallaydi: matni qisqa karta ham qo'shnisi bilan bir xil bo'yda.
  • ul + aria-label — lenta ro'yxat: ekran o'quvchi "Bugungi takliflar, ro'yxat, 5 ta band" deydi.

2.2 Klaviatura bilan

Bobur sichqonchasiz ishlaydi. U lentani qanday suradi? Bu lentada javob oddiy: har kartada havola bor. Chrome'da tekshirdik: Tab bilan to'rtinchi kartaning "Batafsil" havolasiga kelinganda lenta o'zi surildi va karta ko'rindi. Brauzer fokuslangan elementni doim ko'rinadigan joyga olib chiqadi.

Kartalarda havola yoki tugma bo'lmasa, bu ishlamaydi — Tab lentadan sakrab o'tadi. Unda Skroll xulqi darsidagidek lentaning o'ziga tabindex="0" bering: fokus lentaga tushadi va →/← bilan suriladi. Fokus halqasi ko'rinib tursin.

Tekshirib ko'ring: Lentada scroll-padding-inline: 16px o'chirildi, padding qoldi. Karta surilganda qayerga "yopishadi"?

Javob

Lenta konteynerining chap chetiga — ya'ni ekranning eng chetiga. padding faqat lenta boshidagi bo'sh joyni beradi. Snap nuqtasi esa scroll-padding bilan suriladi. Natijada birinchi karta 16 piksel ichkarida boshlanadi, keyingilari esa ekran chetiga yopishib to'xtaydi — noizchil ko'rinadi.

3. Skrollbar: yashirish yoki ingichkalash

3.1 Tuzoq

Dizayner "pastdagi kulrang chiziq xunuk" dedi. Internetda eng ko'p uchraydigan maslahat — skrollbarni yashirish:

html
<style>
  body { font-family: system-ui, sans-serif; }
  .lenta {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 200px;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 8px;
  }
  .lenta div {
    padding: 24px 12px;
    border-radius: 8px;
    background: #2f6b3a;
    color: #fffaf0;
  }
  .yashirin { scrollbar-width: none; }
  .ingichka {
    scrollbar-width: thin;
    scrollbar-color: #2f6b3a #e8f1ec;
  }
</style>
<p>❌ Yashirin skrollbar:</p>
<div class="lenta yashirin" tabindex="0" aria-label="Yashirin">
  <div>Osh</div><div>Lag'mon</div><div>Manti</div>
  <div>Somsa</div><div>Sho'rva</div>
</div>
<p>✅ Ingichka, brend rangida:</p>
<div class="lenta ingichka" tabindex="0" aria-label="Ingichka">
  <div>Osh</div><div>Lag'mon</div><div>Manti</div>
  <div>Somsa</div><div>Sho'rva</div>
</div>

Nimaga qarang: tepadagi lentada skrollbar yo'q — to'rtinchi karta o'ng chetda kesilgan, lekin surish mumkinligini hech narsa aytmaydi. Kompyuterda sichqoncha g'ildiragi faqat tikka aylantiradi — Aziz "Sho'rva" borligini bilmay qoladi. Pastdagisida ingichka yashil skrollbar bor: ko'zga tashlanmaydi, lekin "surish mumkin" deb turadi.

Telefonda farq kamroq: u yerda skrollbar baribir faqat surayotganda chiqadi. Muammo asosan kompyuterda.

3.2 Ikki xususiyat

  • scrollbar-width — auto, thin yoki none. 2024-yil dekabrdan Baseline (yangi).
  • scrollbar-color — ikki rang: surgich (thumb) va yo'lak (track). 2025-yil dekabrdan Baseline (yangi).

Qoida: none faqat surishning boshqa ko'rinadigan yo'li bo'lsa — oldinga-orqaga tugmalari yoki nuqtalar. Ranglarni tanlaganda surgich yo'lakdan aniq ajralib tursin: WCAG 1.4.11 grafik elementlar uchun 3:1 kontrast talab qiladi.

Eski saytlarda ::-webkit-scrollbar pseudo-elementlarini uchratasiz — Chrome va Safari'ning eski, nostandart yo'li. Yangi kodda standart scrollbar-width va scrollbar-color ni ishlating. Chrome ikkalasini ham bilsa, standart xususiyat yutadi.

4. Nuqtalar: hamma brauzerda ishlaydigan yo'l

4.1 #havola bilan navigatsiya

Karusel ostidagi nuqtalar "nechanchi slayddasiz" deb aytadi va bosilsa, o'sha slaydga olib boradi. JavaScript'siz eng oddiy yo'l — sahifa ichidagi havolalar: har slaydga id, har nuqta — <a href="#id">. Skroll xulqi darsida scroll-behavior bilan ko'rgan edik: brauzer havola nishonini ko'rinadigan joyga suradi. Nishon gorizontal lenta ichida bo'lsa — lentani yon tomonga suradi.

html
<style>
  body { font-family: system-ui, sans-serif; }
  .taklif {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 100%;
    max-width: 320px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-snap-stop: always;
  }
  .taklif section {
    scroll-snap-align: start;
    padding: 32px 16px;
    text-align: center;
    background: #2f6b3a;
    color: #fffaf0;
  }
  .taklif h3 { margin: 0; }
  @media (prefers-reduced-motion: no-preference) {
    .taklif { scroll-behavior: smooth; }
  }
  .nuqtalar {
    display: flex;
    justify-content: center;
    gap: 4px;
    max-width: 320px;
    scroll-target-group: auto;
  }
  .nuqtalar a {
    padding: 4px 10px;
    border-radius: 999px;
    color: #2f6b3a;
  }
  .nuqtalar a:target-current {
    background: #2f6b3a;
    color: #fffaf0;
  }
</style>
<div class="taklif" tabindex="0" aria-label="Bugungi takliflar">
  <section id="taklif-1"><h3>Osh — 35 000</h3></section>
  <section id="taklif-2"><h3>Lag'mon — 28 000</h3></section>
  <section id="taklif-3"><h3>Manti — 30 000</h3></section>
</div>
<nav class="nuqtalar" aria-label="Takliflar">
  <a href="#taklif-1">1</a>
  <a href="#taklif-2">2</a>
  <a href="#taklif-3">3</a>
</nav>

Nimaga qarang: "3" ni bosing — lenta silliq surilib, "Manti" ko'rinadi. Chrome'da "3" yashil doiraga aylanadi, "1" esa oddiy havolaga qaytadi. Barmoq bilan surib ko'ring: doira ham ergashadi. Firefox va Safari'da havolalar ishlaydi — lenta suriladi, faqat faol raqam belgilanmaydi.

Chrome'da o'lchadik (natija ostiga uzun bo'sh blok qo'shib): "3" bosilganda lenta 640 pikselga — ikki slayd eniga — surildi, manzil satriga #taklif-3 yozildi va sahifa ham 8 piksel pastga — lenta ustki chetiga — aylandi. Bu #havola ning tabiati: nishonni ko'rinadigan qiladi va URL'ni o'zgartiradi. Kamchiligi — har bosish brauzer tarixiga yoziladi: "Orqaga" tugmasi avval slaydlar bo'ylab qaytadi.

4.2 Yangi ikki narsa

  • scroll-snap-stop: always — bitta kuchli surish bilan uch slayddan sakrab o'tib ketmaslik uchun: har surish faqat keyingi slaydgacha (Skroll xulqi).
  • scroll-target-group: auto — "bu guruhdagi havolalarning nishonlarini kuzat". Hozir ko'rinib turgan nishonga olib boradigan havola :target-current holatini oladi. Ilgari buning uchun JavaScript skroll holatini kuzatardi.

scroll-target-group va :target-current — Baseline emas, faqat Chrome/Edge'da (140 va 135 dan). Boshqa brauzerlarda qoida tashlanadi — nuqtalar ishlaydi, faqat faoli ajralib turmaydi. Bu — zaxirasi o'z-o'zidan tayyor, progressive enhancement.

Tekshirib ko'ring: Nima uchun nuqtalar button emas, a?

Javob

JavaScript'siz tugma hech narsa qila olmaydi — surishni faqat skript bajaradi. <a href="#taklif-3"> esa brauzerning o'z xulqi: nishonga olib boradi. Ma'nosi ham to'g'ri: havola "sahifaning shu joyiga o'tish". Shuning uchun ular nav ichida turibdi.

5. To'liq CSS karusel: ::scroll-button va ::scroll-marker

5.1 Brauzer o'zi yaratadigan tugmalar

Yangi paydo bo'layotgan CSS darsida ikki yangi pseudo-elementni qisqa ko'rgan edik:

  • ::scroll-button(<yo'nalish>) — skroll konteynerining oldinga-orqaga tugmalari. (left), (right), (up), (down) yoki mantiqiy (inline-start), (inline-end); (*) — hammasi birdan.
  • ::scroll-marker — har slayd uchun bittadan "nuqta". Ular konteynerning ::scroll-marker-group i ichida to'planadi. Guruh qayerda chiqishini scroll-marker-group: after (yoki before) aytadi.

Endi ularni to'liq karuselga yig'amiz va tugmalarni anchor positioning bilan slayd ustiga qo'yamiz:

html
<style>
  body { font-family: system-ui, sans-serif; }
  .karusel {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 100%;
    max-width: 320px;
    margin: 0;
    padding: 0;
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-marker-group: after;
    anchor-name: --karusel;
  }
  @media (prefers-reduced-motion: no-preference) {
    .karusel { scroll-behavior: smooth; }
  }
  @supports selector(::scroll-button(*)) {
    .karusel { scrollbar-width: none; }
  }
  .karusel li {
    scroll-snap-align: center;
    padding: 40px 48px;
    text-align: center;
    background: #2f6b3a;
    color: #fffaf0;
  }
  .karusel::scroll-button(*) {
    position: absolute;
    position-anchor: --karusel;
    align-self: anchor-center;
    width: 36px;
    height: 36px;
    border: 0;
    border-radius: 50%;
    background: #fffaf0;
    color: #1f2a24;
  }
  .karusel::scroll-button(*):focus-visible {
    outline: 3px solid #1a5d1a;
    outline-offset: 2px;
    box-shadow: 0 0 0 2px #fffaf0;
  }
  .karusel::scroll-button(*):disabled { opacity: 0.4; }
  .karusel::scroll-button(left) {
    content: "◀" / "Oldingi taklif";
    left: calc(anchor(left) + 6px);
  }
  .karusel::scroll-button(right) {
    content: "▶" / "Keyingi taklif";
    right: calc(anchor(right) + 6px);
  }
  .karusel::scroll-marker-group {
    display: flex;
    justify-content: center;
    gap: 8px;
    max-width: 320px;
    padding-top: 8px;
  }
  .karusel li::scroll-marker {
    content: "" / attr(aria-label);
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #c9d6cf;
  }
  .karusel li::scroll-marker:target-current {
    background: #2f6b3a;
  }
</style>
<ul class="karusel" aria-label="Bugungi takliflar">
  <li aria-label="3 dan 1">Osh — 35 000 so'm</li>
  <li aria-label="3 dan 2">Lag'mon — 28 000 so'm</li>
  <li aria-label="3 dan 3">Manti — 30 000 so'm</li>
</ul>

Nimaga qarang (Chrome'da): yashil slayd ustida chap va o'ng chetda ikki oq doira — "◀" va "▶". "◀" xira: orqaga yo'l yo'q, brauzer uni o'zi o'chirib qo'ydi. Ostida uchta nuqta, birinchisi to'q yashil. "▶" ni bosing — "Lag'mon" ga suriladi, ikkinchi nuqta yashil bo'ladi, "◀" yoqiladi. Nuqtani bosish ham to'g'ridan-to'g'ri o'sha slaydga olib boradi.

Firefox va Safari'da: tugma ham, nuqta ham yo'q, skrollbar ko'rinadi — oddiy magnitli lenta. Ma'lumot yo'qolmaydi.

5.2 Accessibility: brauzer nima berdi

Chrome 154 ning accessibility daraxtini ochib ko'rdik:

  • Tugmalar — haqiqiy button, nomi content dagi / dan keyingi matn: "Oldingi taklif", "Keyingi taklif". Birinchi slaydda "Oldingi taklif" — disabled.
  • Nuqtalar guruhi — navigation, ichida har nuqta link, nomi — slaydning aria-label i: "3 dan 1", "3 dan 2". Shuning uchun content: "" / attr(aria-label) yozdik — nuqtaning ko'rinadigan matni yo'q, lekin eshitiladigan nomi bor.
  • Tugmalar Tab bilan keladi va Enter bilan bosiladi — oddiy tugma kabi. Fokus halqasi — «Bahor»ning ikki rangli halqasi (CSS'da accessibility): yashil slayd ustida to'q outline ko'rinmay qolsa ham, ichidagi qaymoq box-shadow chizig'i ko'rinadi.

Bitta cheklov: ko'rinishni qat'iy nazorat qilib bo'lmaydi. Masalan, ::scroll-button ichiga SVG ikonka qo'yish yoki tugmani slayddan tashqariga chiqarish murakkabroq. Dizayn juda o'ziga xos bo'lsa, hozircha JavaScript karusel qulayroq.

5.3 Tugmalar joyi: anchor positioning

::scroll-button lar karuselning ichida emas, yonida chiziladi. Ularni slayd ustiga qo'yish uchun Anchor positioning: karusel — langar (anchor-name: --karusel), tugmalar — unga bog'langan. align-self: anchor-center — tik bo'yicha karusel o'rtasiga. left: calc(anchor(left) + 6px) — karuselning chap chetidan 6 piksel ichkariga.

Slayd ichidagi padding: 40px 48px — chap va o'ngda tugmalar uchun joy: matn tugma ostida qolmasin.

5.4 Brauzer holati

Baseline ma'lumoti bo'yicha:

Imkoniyat Holat
scroll-snap Keng tarqalgan Baseline (2022-yil iyuldan)
::scroll-button() Baseline emas: faqat Chrome/Edge 135 dan
::scroll-marker, scroll-marker-group Baseline emas: faqat Chrome/Edge 135 dan
:target-current Baseline emas: faqat Chrome/Edge 135 dan
scroll-target-group Baseline emas: faqat Chrome/Edge 140 dan

Zaxira strategiyasi natijadagidek: skrollbarni faqat tugmalar bor joyda yashiring — @supports selector(::scroll-button(*)). Bu shart "brauzer shu pseudo-elementni taniydimi?" deb so'raydi (Brauzer mosligi). Taniydigan Chrome'da skrollbar yo'q, lekin tugmalar va nuqtalar bor. Tanimaydigan brauzerda skrollbar joyida qoladi. Hech bir brauzerda foydalanuvchi "surish mumkinmi?" degan savol bilan qolmaydi.

Tekshirib ko'ring: Karuselda @supports yo'q — scrollbar-width: none to'g'ridan-to'g'ri .karusel ga yozilgan. Safari foydalanuvchisi nimani ko'radi?

Javob

Birinchi slaydni va o'ngda hech narsani. Tugma ham, nuqta ham yo'q (Safari ::scroll-button ni tanimaydi), skrollbar ham yashirilgan. Barmoq bilan surish telefonda ishlaydi, lekin kompyuterda sichqonchali foydalanuvchi qolgan slaydlar borligini bilmaydi. Shuning uchun yashirish — faqat @supports ichida.

6. Avto-aylanish va harakat

6.1 Nega deyarli har doim yomon

Avto-aylanish (autoplay) — karusel o'zi, bir necha soniyada keyingi slaydga o'tadi. Dizaynerlar uni yaxshi ko'radi, foydalanuvchilar esa — yo'q:

  • o'qiyotgan matn qo'l ostidan ketib qoladi;
  • harakat diqqatni sahifaning qolgan qismidan tortib oladi;
  • bosh aylanishi bor odamga zarar (Harakat etikasi).

6.2 Agar baribir kerak bo'lsa

CSS o'zi karuselni vaqt bo'yicha surolmaydi — bu JavaScript ishi: taymer va scrollBy() metodi. Tilni 08-qismdan, sahifani boshqarishni 09-qismdan o'rganamiz. Lekin qoidalar hozirdan aniq (Harakat etikasi darsida boshlagan edik):

  1. To'xtatish tugmasi majburiy — harakat 5 soniyadan uzoq davom etsa, WCAG 2.2.2 "Pause, Stop, Hide" talabi. Tugma karuseldan oldin tursin: Tab bilan birinchi unga yetib kelinsin.
  2. Sichqoncha ustida yoki fokus ichida — to'xtaydi.
  3. prefers-reduced-motion: reduce bo'lsa — umuman yoqilmaydi. JavaScript bu sozlamani matchMedia bilan o'qiydi.
  4. Slayd almashishi — scroll-behavior bilan silliq, faqat harakatga ruxsat bo'lsa. Natijalarimizdagi kabi, smooth doim no-preference bloki ichida.

To'xtatish tugmasining ko'rinishi — CSS ishi: u ham oddiy tugma, Tugmalar tizimi darsidagi qoidalar bilan. Ichidagi belgi holatni aytsin: " To'xtatish" va "▶ Davom ettirish".

Tekshirib ko'ring: Nega to'xtatish tugmasi karuseldan keyin emas, oldin turishi kerak?

Javob

Klaviatura foydalanuvchisi Tab bilan sahifani yuqoridan pastga yuradi. Tugma karuseldan keyin tursa, u avval aylanib turgan slaydlar ichidagi havolalardan o'tishi kerak — kontent qo'l ostidan qochib turadi. Tugma oldinda bo'lsa, u harakatni kontentga yetmasdan to'xtatadi.

7. Karusel semantikasi

ARIA patternlari darsida karusel tuzilmasining g'oyasini ko'rgan edik. Qisqa eslatma:

html
<section aria-roledescription="karusel"
         aria-label="Bugungi takliflar">
  <ul>
    <li role="group" aria-roledescription="slayd"
        aria-label="3 dan 1">Osh — 35 000 so'm</li>
    <!-- ... -->
  </ul>
</section>
  • aria-roledescription — rolning o'qiladigan nomini almashtiradi: ekran o'quvchi "hudud" o'rniga "karusel", "guruh" o'rniga "slayd" deydi. Faqat shu kabi joylarda.
  • aria-label="3 dan 1" — slayd tartibi. ::scroll-marker shu nomni oladi.

Oddiy "kartalar lentasi"da bularning keragi yo'q — u shunchaki ro'yxat (ul + aria-label). aria-roledescription faqat haqiqiy, slaydma-slayd karuselga.

8. Kutubxonalar: Swiper va Embla qachon kerak

Ko'p loyihalarda karusel uchun JavaScript kutubxona ulanadi. Eng mashhurlari — Swiper (hozir 14.3 versiya) va Embla Carousel 8.6-bob. Ular npm orqali o'rnatiladi — dasturchilar kodini tarqatadigan umumiy ombor. npm'ni keyingi qismlarda to'liq o'rganamiz, hozir bilish shart emas. Versiyalar dars yozilgan kuni shu ombordan tekshirildi.

Kerak bo'lsa CSS yetadimi
Kartalar lentasi, magnit Ha — scroll-snap
Nuqtalar, tugmalar Chrome'da ha; hamma joyda — #havola yoki JS
Cheksiz aylanish (oxiridan boshiga) Yo'q — JS
Kompyuterda sichqoncha bilan "tortib" surish Yo'q — JS
Avto-aylanish Yo'q — JS (va o'ylab ko'ring)
Ikki karusel sinxron (katta rasm + kichiklari) Yo'q — JS

Embla ichida ham aynan skroll va snap g'oyasi bor, Swiper esa o'z harakat tizimiga ega. Kutubxona tanlashdan oldin savol bering: "Menga haqiqatan karusel kerakmi yoki oddiy lenta yetadimi?". Ko'pincha lenta yetadi — va u 0 kilobayt JavaScript.

9. Ko'p uchraydigan xatolar

9.1 Skrollbar hamma joyda yashirilgan

scrollbar-width: none — va boshqa navigatsiya yo'q. Kompyuterda lenta "qotib qolgandek". Tuzatish: thin + brend rangi yoki @supports selector(::scroll-button(*)) ichida yashirish.

9.2 Hamma karta to'liq sig'di — "keyingisi" ko'rinmaydi

Karta eni 100% ga juda aniq tushdi va keyingi karta umuman ko'rinmaydi. Foydalanuvchi surish mumkinligini sezmaydi. Tuzatish: 75–85% en yoki nuqtalar.

9.3 scroll-behavior: smooth shartsiz

Harakat kamaytirilgan qurilmada ham lenta uzoq suriladi. Tuzatish: @media (prefers-reduced-motion: no-preference) ichida.

9.4 Muhim ma'lumot ikkinchi slaydda

"Bugun yopiqmiz" e'loni karuselning uchinchi slaydida. Uni hech kim ko'rmaydi. Tuzatish: muhim xabar — sahifaning o'zida, karusel faqat "qo'shimcha" narsalar uchun.

9.5 Tugmalar matnni yopdi

::scroll-button lar slayd ustida, matn ostida qoldi. Tuzatish: slaydga tugmalar eniga yarasha padding-inline.

10. Mashqlar

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

1-mashq (oson): Kompyuterda uch karta

«Bugungi takliflar» lentasini o'zgartiring: telefonda karta eni 85%, 40rem dan keng ekranda esa ekranning roppa-rosa uchdan biri (oraliqlarni hisobga olib).

Ishora: grid-auto-columns qiymatini media query ichida almashtiring (Media queries); oraliqni hisobga olish uchun calc() (Matematik funksiyalar).

Yechim
css
.lenta {
  grid-auto-columns: 85%;
}

@media (min-width: 40rem) {
  .lenta {
    grid-auto-columns: calc((100% - 2 * 12px) / 3);
  }
}

Uch karta orasida ikkita 12 piksellik oraliq bor: 100% - 24px, keyin uchga bo'lamiz. 100% bu yerda — lentaning padding siz, ichki eni. Beshta karta bo'lsa, kompyuterda uchtasi ko'rinadi, qolgan ikkitasiga suriladi. To'rtinchisi chetdan ko'rinmaydi — shuning uchun katta ekranda nuqtalar yoki tugmalar qo'shish maqsadga muvofiq.

2-mashq (o'rta): Nuqtalar ko'rinishi

#havola nuqtali natijadagi raqamlarni haqiqiy "nuqta"larga aylantiring: 12 pikselli doiralar, faoli yashil, qolganlari och kulrang. Lekin barmoq bilan bosish maydoni kamida 24×24 piksel qolsin va raqam ekran o'quvchiga eshitilsin.

Ishora: raqam matnini ko'zdan yashirib, ekran o'quvchiga qoldirish — korinmas qoidalari: 1×1 piksel, overflow: hidden, clip-path: inset(50%) (position); doira — ::before (Pseudo-elementlar); bosish maydoni — havolaning o'zi.

Yechim
html
<nav class="nuqtalar" aria-label="Takliflar">
  <a href="#taklif-1"><span class="korinmas">1-taklif</span></a>
  <a href="#taklif-2"><span class="korinmas">2-taklif</span></a>
  <a href="#taklif-3"><span class="korinmas">3-taklif</span></a>
</nav>
css
.nuqtalar a {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
}

.nuqtalar a::before {
  content: "";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #c9d6cf;
}

.nuqtalar a:target-current {
  background: none;
}

.nuqtalar a:target-current::before {
  background: #2f6b3a;
}

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

Havola 24×24 — WCAG 2.5.8 minimumi (O'lchamlar); ko'rinadigan doira 12 piksel, lekin bosish maydoni butun havola. Ekran o'quvchi "1-taklif, havola" deydi. Faol holat faqat Chrome'da ko'rinadi — boshqa brauzerda uchala doira bir xil, lekin ishlaydi.

3-mashq (qiyin): Stajyorning karuseli

Stajyor «Bahor» bosh sahifasiga karusel qo'ydi:

css
.karusel {
  display: flex;
  overflow-x: hidden;
  scroll-snap-type: x;
  scroll-behavior: smooth;
  scrollbar-width: none;
}

.karusel li {
  width: 100%;
}

Shikoyatlar:

  1. Kartalar bir-biriga siqilib, hammasi bitta ekranga sig'ib qoldi.
  2. Tuzatilgach, barmoq bilan ham surib bo'lmadi.
  3. Surilgan lenta karta o'rtasida to'xtab qoladi.
  4. Kompyuterda qolgan kartalar borligini hech narsa ko'rsatmaydi.
  5. Harakatni kamaytirgan foydalanuvchi shikoyat qildi.

Har muammoning sababini toping va CSS'ni to'liq tuzating. Chrome'da tugma va nuqtalar ham bo'lsin.

Ishora: 1 — flex elementlarning qisqarishi; 2 — overflow qiymati; 3 — elementlarda nima yetishmayapti; 4 va 5 — «Skrollbar» va «To'liq CSS karusel» bo'limlari.

Yechim
  1. width: 100% flex'da qisqaradi — flex-shrink (flex algoritmi). Grid'ga o'tamiz: grid-auto-columns.
  2. overflow-x: hidden — skroll konteyner, lekin foydalanuvchi surolmaydi. auto kerak.
  3. scroll-snap-align yo'q — magnit bor, nuqtasi yo'q; scroll-snap-type: x esa sukut bo'yicha proximity.
  4. Skrollbar hamma joyda yashirilgan.
  5. smooth shartsiz.
css
.karusel {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-marker-group: after;
  anchor-name: --karusel;
}

.karusel li {
  scroll-snap-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  .karusel {
    scroll-behavior: smooth;
  }
}

@supports selector(::scroll-button(*)) {
  .karusel {
    scrollbar-width: none;
  }
}

Tugmalar va nuqtalarning ko'rinishi — «To'liq CSS karusel» natijasidagi ::scroll-button va ::scroll-marker qoidalari. karusel — namoyish class'i; «Bahor»ning kanonik ro'yxatida yo'q.

4-mashq: Portfolio qadami — telefonda loyihalar lentasi

Portfolio'ning "Loyihalar" sahifasida uch karta bor (Yakuniy loyiha). Telefonda ular ustma-ust turadi va sahifa uzun. Telefonda ularni gorizontal lentaga aylantiring:

  1. 40rem dan tor ekranda .loyihalar — bir qatorli lenta: karta eni 85%, magnitli, keyingi karta chetdan ko'rinsin.
  2. Keng ekranda — hozirgi RAM to'ri o'zgarishsiz.
  3. Kartalar ichidagi subgrid tekislash (sarlavha, tavsif, teglar, havolalar bir chiziqda) lentada ham saqlansin.
  4. Klaviatura bilan har kartaga yetib borish mumkinmi? Tekshiring.
  5. Telefon enida (DevTools → 360 px) va kompyuterda tekshiring, so'ng npm run check.

Ishora: flex emas, grid: grid-auto-flow: column — shunda kartalarning grid-row: span 4 va subgrid'i ishlashda davom etadi. Media query — portfolio'ning mobile-first uslubiga qarama-qarshi yo'nalishda: range sintaksisi (width < 40rem) (Media queries).

Yechim

komponentlar.css dagi .loyihalar qoidasidan keyin:

css
/* --- Telefonda loyihalar — magnitli lenta, kengda RAM to'ri
   (Karusel va gorizontal skroll lentasi darsi) --- */
@media (width < 40rem) {
  .loyihalar {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 85%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    padding-block-end: 0.5rem;
    scrollbar-width: thin;
    scrollbar-color: var(--rang-asosiy) var(--rang-fon-och);
  }

  .loyihalar > article {
    scroll-snap-align: start;
  }
}
  • grid-template-columns: none — RAM to'rining ustunlarini bekor qiladi; endi ustunlarni grid-auto-columns yaratadi, har karta — yangi ustun.
  • Subgrid saqlandi. Har karta hamon grid-row: span 4 — to'rning to'rt qatorini egallaydi va ichidagi bo'laklar qo'shni kartalar bilan bir chiziqda turadi. Chrome'da 360 px da tekshirdik: uch kartaning sarlavhalari va "Saytni ochish" havolalari bir balandlikda.
  • Klaviatura. Har kartada havola bor — Tab bilan keyingi kartaning havolasiga kelinganda lenta o'zi suriladi. Shuning uchun .loyihalar ga tabindex shart emas.
  • Skrollbar ingichka, brend rangida — ranglar tokenlar.css dagi o'zgaruvchilardan, qorong'i rejimda o'zi almashadi.
  • Nega (width < 40rem)? Lenta — faqat telefon uchun istisno. Mobile-first'da uni asosiy qoida qilib, keyin 40rem da RAM ni qaytarish ham mumkin edi, lekin unda Yakuniy loyiha darsidagi to'r qoidasini ko'chirish kerak bo'lardi. Istisno bitta blokda — o'qish oson.

Portfolio'da endi eni bo'yicha to'rtta media query bor: bosh sahifa rasmi, header menyusi (Navbar va mobil menyu darsidan), maxfiylik oynasi (Modal oyna darsidan) va loyihalar lentasi. Hammasi bir xil 40rem chegarasida.

11. Real ishda

  • Onlayn do'konlar va yetkazib berish ilovalari — "Tavsiya etamiz", "Yaqinda ko'rganlaringiz" lentalari. Deyarli hammasi oddiy gorizontal skroll + snap.
  • Kontent saytlarida katta "hero" karusel asta-sekin yo'qolmoqda — uning o'rniga bitta kuchli e'lon va pastda lentalar. Sababi — yuqoridagi foydalanish muammolari.
  • Intervyuda so'raladi: "Karuselni JavaScript'siz qila olasizmi?", "Karusel accessibility'si uchun nima qilish kerak?", "Skrollbarni yashirish yaxshimi?". Scroll-snap, ::scroll-button va WCAG 2.2.2 — tayyor javoblar.
  • Kod ko'rib chiqishda tez-tez uchraydigan xato — overflow-x: hidden + JavaScript transform bilan "qo'lda" yasalgan karusel. U klaviatura, ekran o'quvchi va barmoq bilan surishni buzadi. Skroll asosidagi lenta bularning hammasini bepul beradi.

Xulosa

  • Karuselning asosi — skroll: overflow-x: auto, scroll-snap-type: x mandatory, kartalarga scroll-snap-align; grid-auto-flow: column bilan kartalar siqilmaydi.
  • padding va scroll-padding bir xil; keyingi karta chetdan ko'rinib tursin; overscroll-behavior-x: contain.
  • Skrollbarni yashirmang — ingichkalang (scrollbar-width: thin, scrollbar-color); yashirish faqat @supports selector(::scroll-button(*)) ichida.
  • Nuqtalar hamma joyda — #havola lar; faol nuqta — scroll-target-group + :target-current (Chrome).
  • To'liq CSS karusel — ::scroll-button() va ::scroll-marker (faqat Chrome); boshqa brauzerda oddiy lenta qoladi.
  • Avto-aylanish — JavaScript, to'xtatish tugmasi majburiy, prefers-reduced-motion da o'chiq; murakkab xulq uchun Swiper yoki Embla.

Keyingi dars: HTML email'larni stillash — zamonaviy CSS'ning ko'p qismi ishlamaydigan joy: pochta dasturlari uchun jadval, inline stil va MJML.

Manbalar

  • MDN: "CSS carousels", "::scroll-button()", "::scroll-marker", "scroll-target-group", "scrollbar-width" — developer.mozilla.org
  • Chrome for Developers: "Carousels with CSS" — developer.chrome.com
  • W3C: "Understanding Success Criterion 2.2.2: Pause, Stop, Hide" — w3.org/WAI/WCAG22/Understanding
  • WAI-ARIA APG: "Carousel (Slide Show or Image Rotator) Pattern" — w3.org/WAI/ARIA/apg
  • web-features: "scroll-buttons", "scroll-markers", "scroll-target-group", "scrollbar-width" — web-platform-dx.github.io/web-features-explorer
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS karusel va gorizontal skroll lentasi: scroll-snap, ::scroll-button va ::scroll-marker — IlmHamroh