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

CSS 3D transform: perspektiva, preserve-3d va ag'dariladigan karta

Qisqacha: 3D transformlar elementni uchinchi — Z o'qi bo'ylab buradi (rotateX, rotateY) va siljitadi (translateZ). Chuqurlik ko'rinishi uchun perspective kerak: u tomoshabin ekrandan qancha uzoqda turganini bildiradi. Bolalarning 3D fazoda qolishi uchun otaga transform-style: preserve-3d, orqa tomonni yashirish uchun backface-visibility: hidden yoziladi. Shu uchtasi bilan ag'dariladigan karta va kub yasaladi.

Bu darsda

  • rotateX, rotateY, rotateZ va translateZ ni ishlatasiz va ular nima uchun perspektivasiz "yassi" ko'rinishini tushuntirasiz.
  • perspective funksiyasi va xususiyatini farqlaysiz, perspective-origin bilan "ko'z" joyini o'zgartirasiz.
  • transform-style: preserve-3d va backface-visibility: hidden bilan ag'dariladigan karta yasaysiz.
  • 3D sahnani "yassilab" qo'yadigan xususiyatlarni bilasiz.
  • Ag'dariladigan kartani klaviatura, telefon va ekran o'quvchi uchun ham ishlaydigan qilasiz.

Oldin bilishingiz kerak: 2D transformlar, Grid'da joylashtirish, Foydalanuvchi afzalliklari.

1. Nega bu kerak?

O'tgan darsda elementni tekislikda siljitdik, burdik, kattalashtirdik. Hammasi ekran yuzasida bo'ldi — xuddi stol ustidagi qog'ozni surgandek.

Endi qog'ozni stoldan ko'taramiz. Jasur aka menyu kartalarining orqa tomonida taom tarkibini ko'rsatmoqchi: mehmon kartaga sichqoncha olib borsa, u o'yin kartasidek ag'darilsin. Old tomonda — "Osh, 35 000 so'm", orqada — "guruch, sabzi, go'sht, zira".

Bunday effekt uchun element ekrandan "chiqib", o'z o'qi atrofida aylanishi kerak. Bu — 3D transformlar. Ular kam ishlatiladi, lekin to'g'ri joyda sahifani jonli qiladi: ag'dariladigan kartalar, 3D galereya, mahsulotni har tomondan ko'rsatish.

2. Uchinchi o'q: Z

2.1 Uch o'q

Ekranda ikki o'qni bilamiz: X — o'ngga, Y — pastga. Uchinchisi — Z o'qi: ekrandan sizga qarab chiqadi. Musbat Z — sizga yaqinroq, manfiy — ekran ichkarisiga, uzoqroq.

Har o'q atrofida burish mumkin:

Funksiya Qaysi o'q atrofida Hayotdagi misol
rotateX(45deg) Gorizontal o'q Noutbuk qopqog'i ochilishi
rotateY(45deg) Vertikal o'q Eshik ochilishi
rotateZ(45deg) Ekrandan chiqqan o'q Soat mili — oddiy rotate()

rotateZ() — o'tgan darsdagi rotate() ning aynan o'zi. Qolgan ikkitasi yangi.

2.2 Perspektivasiz 3D — yassi

Keling, sinaymiz: kvadratga transform: rotateY(60deg) beramiz. Kutganimiz — eshikdek burilgan kvadrat. Chrome'da o'lchadik: 100×100 kvadrat 50×100 bo'lib qoldi. Hech qanday chuqurlik yo'q — kvadrat shunchaki torayib qoldi.

Sababi: brauzer 3D ni hisoblaydi, lekin chizishda uni ekranga to'g'ridan-to'g'ri tushiradi — xuddi quyosh tik turganda devorga tushgan soya kabi. Kvadrat burildi, lekin uning "uzoq" va "yaqin" chetlari bir xil o'lchamda chizildi. Biz faqat uning "soyasini" ko'ramiz: 60 gradusga burilgan eshikning soyasi ham eshik enining aynan yarmi bo'ladi.

translateZ(100px) esa umuman ko'rinmadi: kvadrat 100 piksel "yaqinlashdi", lekin yaqinlashgan narsani kattaroq ko'rsatadigan "ko'z" yo'q. O'lcham 100×100 qoldi.

Chuqurlik uchun brauzerga bitta narsani aytish kerak: tomoshabin qayerda turibdi?

3. Perspektiva

3.1 perspective() funksiyasi

Perspektiva (perspective) — tomoshabinning ko'zidan ekrangacha bo'lgan masofa. Temir yo'lni eslang: relslar parallel, lekin uzoqda bir nuqtada tutashgandek ko'rinadi. Yaqin narsa katta, uzoq narsa kichik — perspektiva shu.

css
.kvadrat {
  transform: perspective(400px) rotateY(60deg);
}

"Ko'z ekrandan 400 piksel uzoqda." Endi Chrome o'lchashi boshqacha: kvadrat 50.6×112.1 bo'ldi. Bizga yaqinlashgan cheti 112 piksel baland bo'lib ketdi, uzoqlashgani — kichraydi. Mana chuqurlik.

translateZ ham endi ishlaydi:

Transform Chrome o'lchagan o'lcham
translateZ(100px) 100 × 100 — o'zgarmadi
perspective(400px) translateZ(100px) 133.3 × 133.3 — yaqinlashdi
perspective(400px) translateZ(-200px) 66.7 × 66.7 — uzoqlashdi

Hisob oddiy: 400 / (400 − 100) = 1.33. Ko'zga 100 piksel yaqinlashgan narsa 1.33 barobar kattaroq ko'rinadi.

Diqqat: perspective() funksiyasi birinchi yozilishi kerak. Masalan, rotateY(60deg) perspective(400px) deb yozsak, Chrome'da o'lcham yana 50×100 chiqdi — perspektivasiz bilan bir xil. O'tgan darsdagi tartib qoidasini eslang: funksiyalar chapdan o'ngga ishlaydi, perspective() esa faqat o'zidan keyingilarga "ko'z" beradi.

3.2 Masofa kichik — effekt kuchli

Qiymat qancha kichik bo'lsa, ko'z shuncha yaqin, buzilish shuncha kuchli. Bir xil rotateY(50deg) ni uch masofada ko'ramiz:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-ikkinchi: #5b6660;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  .uchta {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    padding: 1.5rem 0.5rem;
    text-align: center;
  }
  .joy {
    width: 6rem;
    height: 6rem;
    margin-inline: auto;
    outline: 2px dashed var(--rang-ikkinchi);
  }
  .kvadrat {
    display: grid;
    place-items: center;
    height: 100%;
    background-color: var(--rang-asosiy);
    color: var(--rang-fon);
    font-size: 1.5rem;
    font-weight: bold;
  }
  .p1 { transform: perspective(200px) rotateY(50deg); }
  .p2 { transform: perspective(600px) rotateY(50deg); }
  .p3 { transform: perspective(2000px) rotateY(50deg); }
  p { font-size: 0.8rem; }
</style>
<div class="uchta">
  <div>
    <div class="joy"><div class="kvadrat p1">Osh</div></div>
    <p><code>perspective(200px)</code></p>
  </div>
  <div>
    <div class="joy"><div class="kvadrat p2">Osh</div></div>
    <p><code>perspective(600px)</code></p>
  </div>
  <div>
    <div class="joy"><div class="kvadrat p3">Osh</div></div>
    <p><code>perspective(2000px)</code></p>
  </div>
</div>

Nimaga qarang: chapdagi kvadratning yaqin cheti punktir ramkadan ancha baland chiqib ketgan — ko'z juda yaqin, buzilish kuchli. O'ngdagisi deyarli yassi, faqat torayib qolgan. Chrome o'lchadi: 100 pikselli kvadratning bo'yi 200px da 123.7, 2000px da 102.0 bo'ldi.

Amalda 600–1000 piksel (yoki 40rem–60rem) tabiiy ko'rinadi. 300 dan kichik qiymat — "baliq ko'zi" effekti, faqat ataylab kerak bo'lsa.

Tekshirib ko'ring: perspective(500px) translateZ(250px) bo'lgan 100 pikselli kvadrat qancha katta ko'rinadi? Formula: 500 / (500 − 250).

Javob

2 barobar — 200×200 piksel. Kvadrat ko'z bilan ekranning aynan o'rtasiga chiqdi: masofa ikki barobar qisqardi, o'lcham ikki barobar oshdi. translateZ 500 ga yetsa, kvadrat "ko'zning ichiga" kiradi va brauzer uni umuman chizmaydi.

3.3 perspective xususiyati: umumiy sahna

Funksiyadan tashqari, xuddi shu nomli xususiyat ham bor. Farqi — kimga yoziladi:

  • transform: perspective(600px) ... — elementning o'ziga. Har element o'z ko'zi bilan.
  • perspective: 600px — otaga. Hamma bolalar bitta ko'z bilan, bitta sahnada ko'riladi.

Farqni uchta bir xil burilgan karta bilan ko'ramiz:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  .qator {
    display: flex;
    justify-content: space-around;
    padding-block: 1rem;
  }
  .karta {
    display: grid;
    place-items: center;
    width: 6rem;
    height: 7rem;
    background-color: var(--rang-asosiy);
    color: var(--rang-fon);
    font-weight: bold;
  }
  .funksiya .karta {
    transform: perspective(500px) rotateY(35deg);
  }
  .sahna {
    perspective: 500px;
  }
  .sahna .karta {
    transform: rotateY(35deg);
  }
  h3 { margin: 1rem 0 0; font-size: 1rem; }
</style>
<h3>Har kartada perspective() funksiyasi</h3>
<div class="qator funksiya">
  <div class="karta">Osh</div>
  <div class="karta">Lag'mon</div>
  <div class="karta">Manti</div>
</div>
<h3>Otada perspective xususiyati</h3>
<div class="qator sahna">
  <div class="karta">Osh</div>
  <div class="karta">Lag'mon</div>
  <div class="karta">Manti</div>
</div>

Nimaga qarang: tepadagi uchta karta — bir xil nusxa, har biri o'z ko'zidan ko'rilgan. Pastdagilar har xil: chapdagi "Osh" keng va bizga qaragandek, o'rtadagisi tepadagilarga o'xshaydi, o'ngdagi "Manti" esa deyarli yonboshidan ko'rinadi. Ko'z sahna markazida turibdi va har kartaga o'z burchagidan qaraydi. Bu haqiqiy sahnaga o'xshaydi: xonada turib, derazalarga qarasangiz, har deraza sizga boshqacha burchak ostida ko'rinadi.

Qoida: bitta element bo'lsa — funksiya. Bir necha element bitta sahnada bo'lsa (galereya, kub, kartalar to'plami) — otaga xususiyat.

3.4 perspective-origin: ko'z qayerda

perspective xususiyati bilan birga perspective-origin ishlaydi: ko'z sahnaning qaysi nuqtasiga qarab turibdi. Odatda — markaz (50% 50%). perspective-origin: top — ko'z tepada, sahnaga yuqoridan qaraydi: rotateX bilan yotqizilgan elementlarning ustki tomoni ko'rinadi. perspective-origin: left — ko'z chapda.

Bu transform-origin dan farq qiladi: transform-origin — element qayerdan aylanadi, perspective-origin — tomoshabin qayerdan qaraydi. U faqat perspective xususiyatiga ishlaydi, funksiyaga emas.

4. transform-style: preserve-3d: bolalar ham 3D da

4.1 Muammo: sahna yassilanadi

Kub yasamoqchimiz: oltita tomon, har biri o'z joyiga burilgan. Tomonlar bitta div ichida — shu div ni aylantirsak, butun kub aylanishi kerak.

Lekin odatda element o'z bolalarini yassilaydi: bolalar qanchalik 3D burilgan bo'lmasin, ota ularni o'z tekisligiga surat qilib "bosib" qo'yadi. Keyin shu yassi suratni aylantiradi. Natijada kub o'rniga ustma-ust tushgan kvadratlar ko'rinadi.

transform-style: preserve-3d otaga "bolalaringni yassilama, ular men bilan bitta 3D fazoda yashasin" deydi. Odatiy qiymat — flat.

4.2 «Bahor» choy qutisi

Kub — 3D ning "salom, dunyo" si. Uni «Bahor» ko'k choy qutisi sifatida yasaymiz. Har tomon avval o'z o'qida buriladi, keyin translateZ bilan markazdan tashqariga — kub yarim eniga — suriladi:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-asosiy-toq: #1a5d1a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  .ikki {
    display: flex;
    justify-content: space-around;
    padding: 3rem 1rem;
    text-align: center;
  }
  .sahna {
    width: 6rem;
    height: 6rem;
    perspective: 600px;
  }
  .kub {
    position: relative;
    height: 100%;
    transform-style: preserve-3d;
    transform: rotateX(-25deg) rotateY(35deg);
  }
  .tomon {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    border: 2px solid var(--rang-fon);
    background-color: var(--rang-asosiy);
    color: var(--rang-fon);
    font-weight: bold;
  }
  .old { transform: translateZ(3rem); }
  .orqa { transform: rotateY(180deg) translateZ(3rem); }
  .ong { transform: rotateY(90deg) translateZ(3rem); }
  .chap {
    transform: rotateY(-90deg) translateZ(3rem);
    background-color: var(--rang-asosiy-toq);
  }
  .tepa {
    transform: rotateX(90deg) translateZ(3rem);
    background-color: var(--rang-urgu);
  }
  .past { transform: rotateX(-90deg) translateZ(3rem); }
  .yassi { overflow: hidden; }
  p { margin-top: 2.5rem; font-size: 0.8rem; }
</style>
<div class="ikki">
  <div>
    <div class="sahna">
      <div class="kub">
        <div class="tomon old">Ko'k choy</div>
        <div class="tomon orqa">5 000</div>
        <div class="tomon ong">so'm</div>
        <div class="tomon chap">«Bahor»</div>
        <div class="tomon tepa">Tepa</div>
        <div class="tomon past">Past</div>
      </div>
    </div>
    <p>✅ <code>preserve-3d</code></p>
  </div>
  <div>
    <div class="sahna">
      <div class="kub yassi">
        <div class="tomon old">Ko'k choy</div>
        <div class="tomon orqa">5 000</div>
        <div class="tomon ong">so'm</div>
        <div class="tomon chap">«Bahor»</div>
        <div class="tomon tepa">Tepa</div>
        <div class="tomon past">Past</div>
      </div>
    </div>
    <p>❌ + <code>overflow: hidden</code></p>
  </div>
</div>

Nimaga qarang: chapda haqiqiy quti — old tomonda "Ko'k choy", chap yonida to'q yashil "«Bahor»", tepada qizg'ish qopqoq. O'ngdagi quti ham xuddi shunday yozilgan, faqat .kub ga overflow: hidden qo'shilgan — va u yassi, burilgan bitta kvadratga aylandi. Ustida hatto orqa tomonning teskari yozuvi ko'rinadi: tomonlar bitta tekislikka ustma-ust "bosildi".

Kubni tuzish tartibi:

  1. .sahna — ko'z: perspective: 600px. U qimirlamaydi.
  2. .kub — preserve-3d va butun qutini burish: biroz tepadan (rotateX(-25deg)) va yondan (rotateY(35deg)).
  3. Har .tomon — position: absolute; inset: 0 bilan hammasi bitta joyda (position). Keyin har biri o'z tomoniga "qaraydi" (rotateY(90deg) — o'ngga) va translateZ(3rem) bilan kub chetiga chiqadi. 3rem — 6rem li qirraning yarmi.

Bu yerda o'tgan darsdagi tartib qoidasi hal qiluvchi: avval burish, keyin siljitish. Tomon burilgach, uning "Z" i endi boshqa tomonga qaraydi — translateZ uni aynan o'sha tomonga suradi.

Tekshirib ko'ring: .ong tomonida rotateY(90deg) translateZ(3rem) o'rniga translateZ(3rem) rotateY(90deg) yozilsa nima bo'ladi?

Javob

Tomon avval ekranga qarab 3rem oldinga chiqadi — ya'ni old tomonning joyiga. Keyin o'sha joyda o'z markazi atrofida 90 gradus buriladi va "old" tomonning o'rtasidan ko'ndalang kesib o'tadi. Kub buziladi. 3D da ham tartib — "avval buril, keyin yur".

4.3 Sahnani nima yassilaydi

overflow: hidden yagona "buzg'unchi" emas. Quyidagilardan biri bo'lsa, preserve-3d yozilgan bo'lsa ham brauzer sahnani yassilaydi (to'liq ro'yxat — MDN'ning "transform-style" sahifasida):

  • overflow — visible dan boshqa qiymat;
  • opacity — 1 dan kichik;
  • filter, clip-path, mask — none dan boshqa (Filterlar, clip-path);
  • isolation: isolate, mix-blend-mode — normal dan boshqa;
  • contain: paint va shunga o'xshashlar.

Chrome'da kubni birma-bir tekshirdik: opacity: 0.9, overflow: hidden, overflow: clip, filter: blur(0) (ko'zga hech narsa qilmaydigan filtr!) va isolation: isolate — beshalasida ham kub yassi kvadratga aylandi.

Yodlash shart emas. Qoida bitta: 3D sahna yassilanib qolsa, preserve-3d li elementda shu ro'yxatdan birini qidiring. Ko'pincha u "kubni chiroyli qilish uchun" qo'shilgan opacity yoki overflow: hidden bo'ladi. Yarim shaffoflik kerak bo'lsa — uni otaga emas, har bir tomonga bering.

5. backface-visibility: orqa tomon

Har elementning old va orqa yuzi bor. 180 gradusga burilgan elementni biz orqasidan ko'ramiz — brauzer uni ko'zgudagidek teskari chizadi, xuddi scale(-1, 1) kabi.

backface-visibility: hidden — "orqam sizga qarasa, meni chizma". Ag'dariladigan karta aynan shunga qurilgan:

  • Old yuz: odatdagidek turadi.
  • Orqa yuz: oldindan 180 gradus burib qo'yilgan — biz uning orqasini ko'ramiz, u yashirin.
  • Ikkalasi bitta joyda, ikkalasiga backface-visibility: hidden.
  • Butun kartani 180 gradus aylantirsak: old yuz orqasi bilan qaraydi — yashirinadi, orqa yuz esa to'g'ri tomoni bilan chiqadi.

Kundalik o'xshatish — ikki tomoni bosilgan tashrif qog'ozi. Bir vaqtda faqat bir tomonini ko'rasiz, o'girsangiz — ikkinchisini.

Baseline ma'lumotiga ko'ra 3D transformlar (perspective, transform-style, backface-visibility bilan birga) 2022-yil martdan hamma asosiy brauzerda bor, 2024-yil sentabrdan esa keng tarqalgan Baseline. Eski maqolalarda -webkit-backface-visibility ni uchratasiz — bu eski Safari uchun yozilgan, bugun kerak emas.

6. «Bahor»: ag'dariladigan menyu kartasi

6.1 Avval — hamma uchun ishlaydigan asos

3D karta chiroyli, lekin uchta guruh uni ko'ra olmaydi:

  • Telefon egalari — sichqoncha yo'q, hover yo'q (Foydalanuvchi afzalliklari).
  • Harakatni kamaytirishni yoqqanlar — aylanish bosh aylantirishi mumkin.
  • Klaviatura bilan yuruvchilar (Bobur) — hover ularga yetib bormaydi.

Shuning uchun Brauzer mosligi darsidagi progressive enhancement: asos — ikki tomon ustma-ust, hammasi o'qiladi. Qo'shimcha — sichqonchali qurilmada va harakat ruxsat bo'lsa, tomonlar bitta joyga yig'iladi va karta ag'dariladi.

Namoyish uchun uchta qisqa class ishlatamiz: aylanma (aylanadigan qism), yuz (old) va orqa.

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
    --rang-matn: #1f2a24;
  }
  body {
    padding: 1rem;
    font-family: system-ui, sans-serif;
    color: var(--rang-matn);
  }
  .taom-karta {
    max-width: 15rem;
    perspective: 60rem;
  }
  .aylanma {
    display: grid;
    gap: 0.5rem;
  }
  .yuz,
  .orqa {
    padding: 1rem;
    border: 2px solid var(--rang-asosiy);
    border-radius: 0.5rem;
    background-color: var(--rang-fon);
  }
  .orqa {
    background-color: var(--rang-asosiy);
    color: var(--rang-fon);
  }
  .orqa a { color: inherit; }
  .taom-nomi { margin: 0; color: var(--rang-asosiy); }
  .narx { color: var(--rang-urgu); font-weight: bold; }

  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .aylanma {
      transform-style: preserve-3d;
      transition: rotate 0.6s;
    }
    .yuz,
    .orqa {
      grid-area: 1 / 1;
      backface-visibility: hidden;
    }
    .orqa {
      rotate: y 180deg;
    }
    .taom-karta:hover .aylanma,
    .taom-karta:focus-within .aylanma {
      rotate: y 180deg;
    }
  }
</style>
<article class="taom-karta">
  <div class="aylanma">
    <div class="yuz">
      <h3 class="taom-nomi">Osh</h3>
      <p class="narx">35 000 so'm</p>
      <p>Tarkibi orqa tomonda</p>
    </div>
    <div class="orqa">
      <p>Guruch, sabzi, piyoz, mol go'shti, zira.</p>
      <p><a href="#">Menyuga o'tish</a></p>
    </div>
  </div>
</article>

Nimaga qarang: kompyuterda karta faqat old tomoni bilan turadi — orqa tomon uning ortida yashiringan. Telefonda (sichqonchasiz) yoki harakatni kamaytirish yoqilgan bo'lsa, old va orqa tomon ustma-ust ko'rinadi — hammasi o'qiladi. Kompyuterda sichqonchani kartaga olib boring: karta 0.6 soniyada vertikal o'q atrofida aylanadi va yashil orqa tomon chiqadi. Tab bilan "Menyuga o'tish" havolasiga borsangiz ham karta ag'dariladi.

6.2 Kodni o'qiymiz

  • perspective kartada, aylanish ichkarida. Ko'z — qimirlamaydigan .taom-karta da. Aylanadigan — .aylanma.
  • grid-area: 1 / 1 — ikkala tomon bitta grid katakchasida, ustma-ust (Grid'da joylashtirish). position: absolute dan afzalligi: katakcha balandroq tomonga moslashadi, matn uzun bo'lsa ham karta "kesilmaydi".
  • rotate: y 180deg — alohida rotate xususiyatining 3D shakli: avval o'q (x, y yoki z), keyin burchak. transform: rotateY(180deg) bilan bir xil.
  • Hover .taom-karta da, aylanish .aylanma da. O'tgan darsdagi titrash tuzog'i bu yerda ayniqsa xavfli. 90 gradusda aylanayotgan element eni nolga tushadi. Hover'ni u o'zida ushlasa, har aylanishda "yo'qolib" qolardi.
  • :focus-within — "ichidagi biror element fokusda" (Holat pseudo-klasslari). Bobur Tab bilan havolaga kelsa, karta o'zi ag'dariladi va u nimani fokuslaganini ko'radi.
  • transition: rotate 0.6s — aylanish sakrab emas, 0.6 soniyada silliq bo'lsin. transition ni keyingi darsda to'liq o'rganamiz. Hozir faqat shuni biling: u o'zgarishni sekinlashtiradi.

6.3 Ekran o'quvchi nima eshitadi

backface-visibility: hidden faqat ko'z uchun. Malika NVDA bilan kartaga kelsa, ikkala tomonni ham eshitadi: "Osh, 35 000 so'm, tarkibi orqa tomonda, guruch, sabzi...". Bu yaxshi — tarkib undan yashirilmasligi kerak.

Lekin "tarkibi orqa tomonda" gapi ekran o'quvchida ma'nosiz. Haqiqiy saytda uni faqat ko'zga ko'rinadigan qilish mumkin — aria-hidden="true" bilan (ARIA asoslari). Asosiy qoida: ag'dariladigan kartada muhim narsani faqat orqa tomonga yashirmang. Narx doim oldda bo'lsin.

7. 3D ning qo'shimcha funksiyalari

To'liqlik uchun — kam uchraydi, lekin kodda ko'rasiz:

Funksiya / xususiyat Ma'nosi
translate3d(x, y, z) Uch o'qda birdan siljitish
scale3d(x, y, z), scaleZ() Z bo'yicha kattalashtirish (qalinligi yo'q elementda sezilmaydi)
rotate3d(1, 1, 0, 45deg) Ixtiyoriy o'q atrofida — birinchi uch son o'q yo'nalishi
matrix3d(...) 16 sonli matritsa — DevTools'da ko'rasiz, qo'lda yozilmaydi
translate: 0 0 50px Alohida xususiyat, uchinchi qiymat — Z
rotate: x 45deg, rotate: 1 1 0 45deg Alohida xususiyat, o'q bilan

Maslahat: Eski maqolalarda transform: translateZ(0) yoki translate3d(0, 0, 0) "sahifani tezlashtirish hiylasi" sifatida uchraydi. U elementni alohida qatlamga chiqaradi. Bugun buning to'g'ri yo'li boshqa, va hiyla o'zi ham xotirani yeydi — Rendering va samaradorlik darsida ko'ramiz. Ko'r-ko'rona nusxalamang.

8. Ko'p uchraydigan xatolar

8.1 Perspektiva yo'q — "3D ishlamayapti"

rotateY(60deg) yozildi, element shunchaki torayib qoldi. Tuzatish: perspective() ni transformning boshiga qo'shing yoki otaga perspective xususiyatini bering.

8.2 Kub yassilanib qoldi

preserve-3d yozilgan, lekin kub bitta kvadrat. Tuzatish: o'sha elementda overflow, opacity, filter yo'qligini tekshiring. DevTools'da ularni birma-bir o'chirib ko'ring (DevTools'da CSS).

8.3 preserve-3d noto'g'ri elementda

preserve-3d 3D bolalari bor elementga yoziladi — kubda .kub ga, kartada .aylanma ga. Uni .sahna ga yozish kubni tiklamaydi: yassilash .kub ning o'zida sodir bo'ladi. preserve-3d meros o'tmaydi — chuqur sahnada har darajaga alohida yoziladi.

8.4 Orqa tomon teskari yozuv bilan ko'rinadi

Karta ag'darildi, lekin old tomon "ko'zgudagi yozuv" bo'lib ko'rinib turibdi. Tuzatish: ikkala tomonga ham backface-visibility: hidden. Faqat bittasiga yozish yetmaydi.

8.5 Faqat hover

Kartaning orqasidagi ma'lumotga telefonda umuman yetib bo'lmaydi. Tuzatish: asos — ikkala tomon ko'rinadi; ag'darish — @media (hover: hover) ichida va :focus-within bilan.

9. Mashqlar

Mashqlarni kurs/mashqlar/06/ papkasida bajaring.

1-mashq (oson): Qopqoq ochiladi

«Bahor» menyusining yuqorisida h2 — "Bugungi taomlar". Uni noutbuk qopqog'idek orqaga 30 gradus yotqizing: pastki cheti joyida qolsin, tepasi ekran ichiga ketsin. Ko'z 600 piksel masofada.

Ishora: qaysi o'q — gorizontal («Uch o'q» jadvali). Pastki chet joyida qolishi uchun — 2D transformlar darsidagi transform-origin. Musbat rotateX tepani ekran ichiga yotqizadimi yoki o'zingizga? Sinab ko'ring.

Yechim
css
h2 {
  transform-origin: bottom;
  transform: perspective(600px) rotateX(30deg);
}

Natija:

html
<style>
  body { padding: 1rem; font-family: system-ui, sans-serif; }
  h2 {
    margin: 0;
    padding: 1rem;
    background-color: #2f6b3a;
    color: #fffaf0;
    text-align: center;
    transform-origin: bottom;
    transform: perspective(600px) rotateX(30deg);
  }
</style>
<h2>Bugungi taomlar</h2>
<p>Osh, lag'mon, manti — har kuni 7:00 dan.</p>

Musbat rotateX elementning tepasini ekran ichiga yotqizadi: yashil blok tepasi torayib, pastga tomon kengaygan trapetsiyaga o'xshaydi. transform-origin: bottom pastki chetni "lo'la" qildi — u paragraf bilan orasidagi masofa o'zgarmadi. Manfiy qiymatda tepa sizga qarab egiladi.

2-mashq (o'rta): Galereyani sahnaga aylantiring

Uchta taom kartasi flex qatorda turibdi. Har biriga transform: perspective(700px) rotateY(20deg) yozilgan. Dizayner: "kartalar bitta devorda turgandek ko'rinsin, har biri alohida emas" dedi.

  1. Kodni qanday o'zgartirasiz?
  2. Ko'zni sahnaning chap chetiga qo'ying. Kartalar qanday o'zgaradi?

Ishora: "Umumiy sahna" bo'limi.

Yechim
css
.qator {
  display: flex;
  gap: 1rem;
  perspective: 700px;
  perspective-origin: left;
}

.qator .taom-karta {
  transform: rotateY(20deg);
}
  1. perspective() funksiyasi kartalardan olib tashlanadi, perspective xususiyati otaga — .qator ga yoziladi. Endi uchala karta bitta ko'z bilan ko'riladi.
  2. perspective-origin: left bilan ko'z chap chetda. Chapdagi kartaga ko'z deyarli ro'para — u eng kam buzilgan. O'ngga borgan sari kartalar ko'proq "yon tomondan" ko'rinadi. .qator — namoyish nomi, haqiqiy «Bahor» menyusida ota element nomi o'z HTML'ingizdagiga qarab bo'ladi.

3-mashq (qiyin): Ikki tomonli aksiya kartasi

Aksiya kartasi: old tomonda "Payshanba — osh kuni!", orqa tomonda "Har payshanba osh 10% arzon: 31 500 so'm". Talablar:

  1. Asos: ikkala tomon ustma-ust ko'rinadi.
  2. Sichqonchali qurilmada va harakat ruxsat bo'lsa — karta gorizontal o'q atrofida (tepadan pastga) ag'dariladi.
  3. Klaviatura uchun: kartaga tabindex="0" berilgan, fokusda ham ag'dariladi.
  4. Orqa tomonda matn teskari chiqmasin.

Ishora: namunadagi rotate: y 180deg ni boshqa o'qqa almashtiring — lekin ikkala joyda: orqa tomonning boshlang'ich burilishida ham, hover'da ham. tabindex="0" li elementning o'zi fokuslanadi — :focus-within o'zini ham qamraydi.

Yechim
html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
  }
  body { padding: 1rem; font-family: system-ui, sans-serif; }
  .karta {
    max-width: 16rem;
    perspective: 50rem;
  }
  .aylanma { display: grid; gap: 0.5rem; }
  .yuz,
  .orqa {
    padding: 1rem;
    border-radius: 0.5rem;
    background-color: var(--rang-urgu);
    color: var(--rang-fon);
    font-weight: bold;
  }
  .orqa { background-color: var(--rang-asosiy); }
  p { margin: 0; }

  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .aylanma {
      transform-style: preserve-3d;
      transition: rotate 0.6s;
    }
    .yuz,
    .orqa {
      grid-area: 1 / 1;
      backface-visibility: hidden;
    }
    .orqa { rotate: x 180deg; }
    .karta:hover .aylanma,
    .karta:focus-within .aylanma {
      rotate: x 180deg;
    }
  }
</style>
<div class="karta" tabindex="0">
  <div class="aylanma">
    <p class="yuz">Payshanba — osh kuni!</p>
    <p class="orqa">Har payshanba osh 10% arzon: 31 500 so'm</p>
  </div>
</div>
  • Ikki joyda ham x: orqa tomon oldindan rotate: x 180deg bilan "yotqizilgan", hover'da butun .aylanma ham x bo'yicha aylanadi. Bittasi y qolsa, orqa tomon ostin-ustun chiqardi — ikki aylanish bir-birini "yopmaydi".
  • tabindex="0" — Klaviatura bilan boshqaruv darsidan: element Tab tartibiga kiradi. :focus-within element o'zi fokusda bo'lganda ham ishlaydi.
  • Chegara radiusi ikkala tomonda — ag'darilganda burchaklar bir xil.
  • 31 500 — 35 000 ning 90 foizi.

4-mashq: Portfolio qadami — bosh sahifa rasmiga chuqurlik

Yakuniy loyiha darsida bosh sahifa keng ekranda ikki ustunli "rasm"ga aylangan edi: chapda matn, o'ngda ish joyi rasmi. Rasmga yengil 3D ko'rinish bering: u matnga qarab biroz burilgan bo'lsin, sichqoncha kelganda esa to'g'rilansin.

  1. Faqat keng ekranda (mavjud @media (width >= 40rem) bloki ichida): rasm vertikal o'q atrofida -10deg ga burilsin, ko'z 50rem masofada.
  2. Sichqonchali qurilmada va harakat ruxsat bo'lsa, hover'da rasm to'g'rilansin.
  3. 768 va 1280 pikselda tekshiring: gorizontal skroll paydo bo'lmadimi? Telefon enida rasm tekis qoldimi?

Ishora: bitta element — demak perspective() funksiyasi. Rasmning qaysi cheti sizga yaqinlashadi: manfiy rotateY da o'ng cheti. Skrollni Yakuniy loyiha darsidagi Console tekshiruvi bilan o'lchang.

Yechim

"4. Layout" bo'limidagi mavjud blokka, rasm qoidasiga bitta qator:

css
@media (width >= 40rem) {
  /* ... bosh sahifa to'ri o'zgarishsiz ... */

  /* Rasm matnga qarab burilgan (3D transformlar darsi) */
  main:has(> img) > img {
    grid-area: rasm;
    transform: perspective(50rem) rotateY(-10deg);
  }
}

"6. Afzalliklar va qurilma" bo'limidagi harakat blokiga (2D transformlar darsida qo'shilgan):

css
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  a[href^="https://"]:hover::after {
    translate: 0.125em -0.125em;
  }

  main > img:hover {
    transform: none;
  }
}

Bosh sahifa to'rini Chrome'da qayta yig'ib o'lchadik. 1280 pikselda rasm 259×173: burilgach o'ng (yaqin) cheti 178 pikselgacha o'sdi, chap cheti kichraydi — rasm matnga qarab "o'girilgan". O'ng cheti main dan atigi 2 piksel chiqadi, sahifa chetigacha esa kamida 1rem bor. 640, 768 va 1280 pikselda gorizontal skroll chiqmadi. Telefon enida media query ishlamaydi — rasm tekis.

Uch nozik joy:

  • Nega perspective() funksiyasi? Rasm bitta — sahna kerak emas. Otaga (main) perspective yozish butun sahifa matnini ham "sahna"ga qo'shardi.
  • Hover sakrab o'zgaradi. Silliq to'g'rilanishni keyingi darsda qo'shamiz.
  • transform stacking context yaratadi (z-index). Rasm atrofida absolute yoki fixed element yo'q — muammo yo'q. Keyinchalik qo'shsangiz, eslang.

10. Real ishda

  • Ag'dariladigan kartalar — o'quv platformalaridagi "so'z kartochkalari" (old tomonda so'z, orqada tarjima), narx jadvallari, jamoa a'zolari kartalari.
  • Mahsulot ko'rinishi — onlayn do'konlarda qutini aylantirib ko'rsatish; murakkabi WebGL va Three.js kabi kutubxonalar bilan qilinadi (kursda kerak bo'lsa alohida ko'ramiz, hozir bilish shart emas).
  • Sahifa o'tishlari — 3D "varaqlash" effektlari. Bugun ular View Transitions bilan birga ishlatiladi.
  • Ehtiyotkorlik — 3D effektlar tez "eskiradi" va harakatga sezgir odamlarni bezovta qiladi. Tajribali dizaynerlar ularni kam va ma'noli joyda ishlatadi (Harakat etikasi).
  • Intervyuda so'raladi: "perspective xususiyati va funksiyasining farqi?", "Ag'dariladigan kartani qanday qilasiz?", "Nega preserve-3d ishlamay qolishi mumkin?"

Xulosa

  • Z o'qi — ekrandan sizga qarab. rotateX, rotateY — 3D burish, translateZ — yaqinlashish/uzoqlashish.
  • Perspektivasiz 3D yassi ko'rinadi: perspective() transformning boshida yoki otada perspective xususiyati.
  • Kichik perspektiva — kuchli buzilish; tabiiy qiymat taxminan 600–1000 piksel.
  • transform-style: preserve-3d bolalarni 3D da saqlaydi; overflow, opacity, filter uni yassilaydi.
  • backface-visibility: hidden ikkala tomonga — ag'dariladigan karta asosi.
  • 3D effekt — qo'shimcha: asos hamma uchun o'qiladigan bo'lsin, ag'darish hover va prefers-reduced-motion sharti bilan.

Keyingi dars: Transition va timing funksiyalari — holatlar orasidagi o'zgarishni silliq qilamiz va harakatga "xarakter" beramiz.

Manbalar

  • MDN: "perspective", "perspective-origin", "transform-style", "backface-visibility", "Using CSS transforms" — developer.mozilla.org
  • W3C: "CSS Transforms Module Level 2" (3D transformlar, yassilash qoidalari) — w3.org/TR/css-transforms-2
  • web.dev: "Learn CSS — Transforms" — web.dev/learn/css
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS 3D transform: perspektiva, preserve-3d va ag'dariladigan karta — IlmHamroh