IlmHamroh
JavaScript Full-stack/6-qism. CSS: harakat, zamonaviy CSS va dizayn1/57-dars25 daqiqa
Mundarija (37)

CSS transform: 2D transformlar — siljitish, burish va kattalashtirish

Qisqacha: transform elementni chizish paytida siljitadi (translate), buradi (rotate), kattalashtiradi (scale) yoki qiyshaytiradi (skew). Element layoutdagi joyini saqlaydi: qo'shnilari surilmaydi. Masalan, transform: translateY(-4px) kartani 4 piksel ko'taradi. Bir nechta funksiya yozilsa, tartib natijani o'zgartiradi. Zamonaviy CSS'da translate, rotate va scale alohida xususiyat sifatida ham bor.

Bu darsda

  • translate, rotate, scale va skew bilan elementni siljitasiz, burasiz, kattalashtirasiz va qiyshaytirasiz.
  • Transform nega qo'shnilarni surmasligini va bu qachon foydali, qachon xavfli ekanini tushuntirasiz.
  • Funksiyalar tartibi natijani qanday o'zgartirishini oldindan ayta olasiz.
  • transform-origin bilan aylanish nuqtasini tanlaysiz.
  • Transformning yon ta'sirlarini bilasiz: inline element, containing block, stacking context, skroll va hover titrashi.

Oldin bilishingiz kerak: position va containing block, z-index va stacking context, Flex naqshlari va markazlash, Yakuniy loyiha: portfolio.

1. Nega bu kerak?

05-qismni tugatdingiz. Yakuniy loyihada portfoliongiz toza asosiy.css ga yig'ildi: rang, shrift, layout, responsive va qorong'i rejim joyida. Sayt chiroyli, lekin "qotib qolgan": hech narsa qimirlamaydi, sichqonchaga faqat rang bilan javob beradi.

06-qismda CSS jonlanadi. Birinchi qadam — elementni joyidan qo'zg'atish.

Chegara va soyalar darsidagi mashqni eslang. «Bahor» kartasiga hover'da kattaroq soya berdik va "karta haqiqatan tepaga siljishi uchun transform kerak" degan edik. Nega margin bilan siljitmadik? Chunki margin layoutni o'zgartiradi. Karta 4 piksel tepaga chiqsa, ostidagi hamma karta ham 4 piksel ko'chadi — butun menyu "sakraydi".

Choyxonadagi manzarani tasavvur qiling. Otabek o'z stulidan turib, xona bo'ylab yuradi. Stul esa unga tegishli bo'lib qoladi — hech kim unga o'tirmaydi, qo'shni stullar surilmaydi. transform xuddi shunday ishlaydi: element "turib yuradi", layoutdagi joyi esa bo'sh saqlanadi.

2. transform va translate(): joyidan qo'zg'atmasdan siljitish

2.1 Birinchi siljitish

Transform (transform) — elementni chizish paytida o'zgartiradigan xususiyat: siljitish, burish, kattalashtirish. Qiymati — bir yoki bir nechta transform funksiyasi. Eng oddiysi — translateY(): elementni vertikal o'q bo'ylab siljitadi.

Ikki ustunni solishtiramiz. Chapda o'rtadagi karta margin-top bilan 24 piksel pastga tushgan, o'ngda — transform: translateY(24px) bilan:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  .ikki {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
  }
  h3 { margin-block: 0 0.5rem; }
  .taom-karta {
    margin-block: 0 0.5rem;
    padding: 0.5rem 0.75rem;
    border: 2px solid var(--rang-asosiy);
    background-color: var(--rang-fon);
  }
  .m { margin-top: 24px; }
  .t { transform: translateY(24px); }
</style>
<div class="ikki">
  <section>
    <h3>margin-top</h3>
    <article class="taom-karta">Osh</article>
    <article class="taom-karta m">Lag'mon</article>
    <article class="taom-karta">Manti</article>
  </section>
  <section>
    <h3>translateY</h3>
    <article class="taom-karta">Osh</article>
    <article class="taom-karta t">Lag'mon</article>
    <article class="taom-karta">Manti</article>
  </section>
</div>

Nimaga qarang: chapda "Lag'mon" pastga tushdi va "Manti" ni ham o'zi bilan itarib ketdi. O'ngda "Lag'mon" ham xuddi shuncha tushdi, lekin "Manti" joyida qoldi — ikki karta ustma-ust chiqdi. Transform qo'shnilarni surmaydi, ular transform bo'lmagandek joylashadi.

Buni brauzerda o'lchab ham ko'rdik (JavaScript bilan — sahifadagi elementlarni o'lchashni 09-qismda o'rganasiz). O'rtadagi kartaga translateY(-20px) berdik: u ekranda 20 piksel tepaga chiqdi, qo'shnilarining koordinatalari esa bir piksel ham o'zgarmadi.

Bu ikki yoqlama:

  • Afzallik: hover'da karta ko'tarilsa, menyu sakramaydi. Brauzer layoutni qayta hisoblamaydi — shuning uchun transform animatsiyada ham eng arzon xususiyatlardan biri (Rendering va samaradorlik darsida sababini ko'ramiz).
  • Xavf: transform bilan siljigan element boshqalarning ustiga chiqishi mumkin. Brauzer unga joy bo'shatmaydi.

"Lag'mon" nega "Manti" ning ustida chiqdi, ostida emas? z-index darsidagi jadvalni eslang: transform stacking context (alohida qatlam) yaratadi. Brauzer bunday elementni oddiy qo'shnilardan keyin chizadi — ya'ni ularning ustida.

2.2 translateX, translateY va translate()

Uchta shakl bor:

Yozuv Nima qiladi
translateX(20px) 20 piksel o'ngga (manfiy — chapga)
translateY(20px) 20 piksel pastga (manfiy — tepaga)
translate(20px, 10px) O'ngga 20, pastga 10

translate() da vergul bor — bu funksiya argumentlari. Bitta qiymat yozilsa (translate(20px)), faqat gorizontal siljiydi.

Yo'nalishlar ekran koordinatasi bo'yicha: X o'ngga, Y pastga o'sadi. Matematikadagi grafikdan farqli — u yerda Y tepaga o'sardi. Shuning uchun "tepaga ko'tarish" — manfiy son: translateY(-4px).

2.3 Foiz — elementning o'z o'lchamidan

Flex naqshlari darsidagi markazlashning oltinchi usulini eslang: top: 50%; left: 50% va translate: -50% -50%. O'shanda "translate foizi elementning o'z o'lchamidan olinadi" degan edik. Endi tekshiramiz: eni 200 pikselli elementga translateX(50%) berdik — Chrome'da u aynan 100 piksel o'ngga siljidi.

Bu position: relative bilan katta farq. position darsida top: 50% containing block'dan hisoblanishini ko'rgan edik. Transform foizi esa doim o'zidan: "o'z enimning yarmi". Shuning uchun o'lchami noma'lum elementni markazlash uchun aynan transform ishlatiladi.

Tekshirib ko'ring: Eni 300 piksel, bo'yi 80 piksel bo'lgan tugmaga transform: translate(-10%, 50%) berildi. U qayerga va qancha siljiydi?

Javob

30 piksel chapga (300 ning 10 foizi, manfiy — chapga) va 40 piksel pastga (80 ning yarmi). Ikkala foiz ham tugmaning o'z o'lchamidan olinadi: birinchisi enidan, ikkinchisi bo'yidan. Qo'shni elementlar joyida qoladi.

3. rotate(): burish

3.1 Burchak va uning birliklari

rotate() elementni burchakka buradi. Musbat burchak — soat mili bo'yicha, manfiy — teskarisiga. Burchak birlik bilan yoziladi:

Birlik Ma'nosi 90° qanday yoziladi
deg gradus, to'liq aylana — 360 90deg
turn aylana, to'liq aylana — 1 0.25turn
rad radian, to'liq aylana — 2π 1.5708rad

Amalda deg va turn ishlatiladi. turn to'liq aylanishlarda qulay: rotate(1turn) — bir marta to'liq aylanish. Birliksiz rotate(45) — xato, brauzer uni tashlab ketadi (CSS nima darsidagi "birlik majburiy" qoidasi).

Burilgan element ko'proq joy egallagandek ko'rinadi. 100×100 pikselli kvadratni 45 gradusga burdik: Chrome o'lchagan chegara to'rtburchagi 141×141 bo'ldi — kvadratning diagonali. Layoutdagi joyi esa 100×100 qoldi. Burchaklari qo'shnilar ustiga chiqishi mumkin.

3.2 «Bahor»: "Yangi" muhri

Jasur aka yangi taomlar kartasida qiyshiq "muhr" ko'rinishini xohlaydi — xuddi qog'ozga bosilgan shtamp kabi. yangi modifikatori 04-qismdan bor. Muhrni ::before bilan chizamiz (Pseudo-elementlar), burchakka position: absolute bilan qo'yamiz, keyin transform bilan biroz tashqariga chiqarib buramiz:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
  }
  body {
    padding: 1.5rem;
    font-family: system-ui, sans-serif;
  }
  .taom-karta {
    position: relative;
    max-width: 16rem;
    padding: 0.75rem 1rem;
    border: 2px solid var(--rang-asosiy);
    border-radius: 0.5rem;
    background-color: var(--rang-fon);
  }
  .taom-nomi {
    margin: 0;
    color: var(--rang-asosiy);
  }
  .narx {
    color: var(--rang-urgu);
    font-weight: bold;
  }
  .yangi::before {
    content: "Yangi";
    position: absolute;
    top: 0;
    right: 0;
    padding: 0.25rem 0.5rem;
    border: 2px solid var(--rang-urgu);
    border-radius: 0.25rem;
    background-color: var(--rang-fon);
    color: var(--rang-urgu);
    font-weight: bold;
    transform: translate(30%, -50%) rotate(-12deg);
  }
</style>
<article class="taom-karta yangi">
  <h3 class="taom-nomi">Manti</h3>
  <p>Narxi: <span class="narx">30 000 so'm</span></p>
</article>

Nimaga qarang: muhr kartaning o'ng yuqori burchagida, chegaradan biroz tashqarida va 12 gradus chapga qiyshaygan. Uch ish birga bajarildi:

  1. position: absolute; top: 0; right: 0 — muhrni kartaning burchagiga qo'ydi.
  2. translate(30%, -50%) — o'z enining 30 foizi o'ngga, o'z bo'yining yarmi tepaga chiqardi. Muhr so'zi uzunroq bo'lsa ham, siljish unga moslashadi.
  3. rotate(-12deg) — soat miliga teskari 12 gradus burdi.

4. scale() va skew()

4.1 scale(): kattalashtirish va kichraytirish

scale() — ko'paytiruvchi, birliksiz son. 1 — asl o'lcham, 1.1 — 10 foiz katta, 0.5 — yarmi.

Yozuv Ma'nosi
scale(1.1) Ikkala o'qda 1.1 marta
scale(2, 0.5) Eni 2 marta, bo'yi yarmi
scaleX(1.5), scaleY(0.8) Faqat bitta o'qda
scale(-1, 1) Gorizontal ko'zgu aksi

200×100 pikselli blokka scale(1.1) berdik. Chrome o'lchadi: ko'rinadigan o'lchami 220×110, chap cheti esa 10 piksel chapga chiqdi. Element markazidan kattalashdi — ikki tomonga teng o'sdi. Qo'shnilar yana joyida qoldi.

Manfiy qiymat elementni ag'daradi. scale(-1, 1) — ko'zgudagidek: chap o'ngga o'tadi. O'ngni ko'rsatadigan strelkani chapga "burish" uchun yangi rasm chizish shart emas.

Diqqat: scale matnni ham kattalashtiradi, lekin font-size ni o'zgartirmaydi. Kattalashgan sarlavha qatorlarga qayta bo'linmaydi va qo'shnilarini surmaydi. Matnni doimiy kattaroq qilish kerak bo'lsa — font-size ishlating. scale — vaqtinchalik effekt uchun: hover, bosilish, paydo bo'lish.

4.2 skew(): qiyshaytirish

skew() to'g'ri to'rtburchakni parallelogrammga aylantiradi — xuddi qutini yon tomondan bosgandek. skewX(-10deg) — gorizontal qiyshaytirish, skewY() — vertikal, skew(x, y) — ikkalasi. Reklama lentalari va "tezlik" hissini beradigan tugmalarda uchraydi.

Ichidagi matn ham qiyshayadi. Matnni to'g'ri qoldirish uchun bolasiga teskari burchak beriladi: ota skewX(-10deg), bola skewX(10deg).

Hammasini yonma-yon ko'ramiz. Punktir ramka — elementning layoutdagi joyi, yashil blok — transformdan keyingi ko'rinishi:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-ikkinchi: #5b6660;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  .galereya {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
    gap: 2rem 1.5rem;
    padding: 1.5rem;
  }
  .joy {
    height: 4.5rem;
    outline: 2px dashed var(--rang-ikkinchi);
  }
  .kvadrat {
    display: grid;
    place-items: center;
    height: 100%;
    background-color: var(--rang-asosiy);
    color: var(--rang-fon);
    font-weight: bold;
  }
  .r { transform: rotate(20deg); }
  .s { transform: scale(1.2); }
  .k { transform: skewX(-15deg); }
  .o { transform: scale(-1, 1); }
  p { margin: 1rem 0 0; font-size: 0.875rem; }
</style>
<div class="galereya">
  <div>
    <div class="joy"><div class="kvadrat r">Osh</div></div>
    <p><code>rotate(20deg)</code></p>
  </div>
  <div>
    <div class="joy"><div class="kvadrat s">Osh</div></div>
    <p><code>scale(1.2)</code></p>
  </div>
  <div>
    <div class="joy"><div class="kvadrat k">Osh</div></div>
    <p><code>skewX(-15deg)</code></p>
  </div>
  <div>
    <div class="joy"><div class="kvadrat o">Osh</div></div>
    <p><code>scale(-1, 1)</code></p>
  </div>
</div>

Nimaga qarang: to'rtala holatda punktir ramka o'z joyida qoldi — layout o'zgarmadi. Burilgan va kattalashgan bloklar ramkadan tashqariga chiqdi. Oxirgisida "Osh" so'zi ko'zgudagidek teskari yozilgan: scale(-1, 1) matnni ham ag'daradi.

Tekshirib ko'ring: Dizayner "tugma bosilganda biroz kichraysin" dedi. scale(0.97) yoki width: 97% — qaysi biri to'g'ri va nega?

Javob

scale(0.97). U faqat chizishni o'zgartiradi: tugma markazidan kichrayadi, qo'shnilar joyida qoladi. width: 97% esa layoutni o'zgartiradi: tugmaning eni otaga bog'liq bo'lib qoladi, matni qatorlarga qayta bo'linishi mumkin va yonidagi elementlar suriladi.

5. Bir nechta funksiya: tartib muhim

transform ga bir nechta funksiyani bo'sh joy bilan ajratib yozish mumkin. «Bahor» muhrida shunday qildik: translate(30%, -50%) rotate(-12deg). Lekin tartib natijani o'zgartiradi.

Sababi — har funksiya elementning o'z koordinatalar tizimini o'zgartiradi. Burilgan elementning "o'ngi" endi ekranning o'ngi emas. Keyingi funksiya shu yangi tizimda ishlaydi.

Kundalik misol. Ikki buyruq bor: "100 qadam yur" va "o'ngga buril". Avval yursangiz, keyin burilsangiz — 100 qadam oldinda, o'ngga qarab turasiz. Avval burilib, keyin yursangiz — 100 qadam o'ng tomonda turasiz. Buyruqlar bir xil, joy boshqa.

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-ikkinchi: #5b6660;
    --rang-fon: #fffaf0;
  }
  body { font-family: system-ui, sans-serif; }
  .ikki {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
  }
  .maydon { height: 11rem; }
  .joy {
    width: 5rem;
    height: 5rem;
    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: 2rem;
  }
  .a { transform: translate(80px) rotate(90deg); }
  .b { transform: rotate(90deg) translate(80px); }
  code { font-size: 0.8rem; }
</style>
<div class="ikki">
  <div>
    <p><code>translate(80px) rotate(90deg)</code></p>
    <div class="maydon">
      <div class="joy"><div class="kvadrat a">→</div></div>
    </div>
  </div>
  <div>
    <p><code>rotate(90deg) translate(80px)</code></p>
    <div class="maydon">
      <div class="joy"><div class="kvadrat b">→</div></div>
    </div>
  </div>
</div>

Nimaga qarang: ikkala strelka ham pastga qaragan — ikkalasi 90 gradus burildi. Lekin chapdagisi 80 piksel o'ngga ketdi, o'ngdagisi esa 80 piksel pastga. O'ngda rotate avval ishladi: elementning "o'ngi" pastga qaradi, keyingi translate(80px) esa shu yangi "o'ng" bo'ylab yurdi. Chrome'da o'lchadik: 100 pikselli siljishda ham xuddi shunday — birinchi holatda x 100 ga oshdi, ikkinchisida y.

Amaliy qoida: avval translate, keyin rotate va scale. Shunda siljish ekran bo'yicha bo'ladi va uni oldindan tasavvur qilish oson. «Bahor» muhri ham aynan shu tartibda yozilgan.

Tekshirib ko'ring: transform: scale(2) translateX(50px) — element ekranda necha piksel o'ngga siljiydi? piksel.

Javob

100 piksel. scale(2) avval ishlaydi va elementning koordinatalarini ikki barobar "cho'zadi". Keyingi translateX(50px) shu cho'zilgan tizimda yuradi: 50 × 2 = 100. translateX(50px) scale(2) deb yozilsa — aynan 50 piksel bo'lardi.

6. Alohida xususiyatlar: translate, rotate, scale

6.1 Sintaksis

Uzoq yillar hamma transform bitta transform xususiyatida yozilardi. Endi uchtasining alohida xususiyati bor:

css
.taom-karta {
  translate: 0 -4px; /* transform: translateY(-4px) kabi */
  rotate: -12deg; /* transform: rotate(-12deg) kabi */
  scale: 1.05; /* transform: scale(1.05) kabi */
}

Farqlarga e'tibor bering: qavs va vergul yo'q, qiymatlar bo'sh joy bilan ajraladi. translate: 10px — faqat gorizontal, translate: 0 10px — faqat vertikal. scale: 1 -1 — vertikal ko'zgu aksi. skew ning alohida xususiyati yo'q — u faqat transform ichida.

Baseline ma'lumotiga ko'ra, alohida transform xususiyatlari 2022-yil avgustdan hamma asosiy brauzerda bor. 2025-yil fevraldan esa keng tarqalgan Baseline — bemalol ishlatsa bo'ladi.

6.2 Qo'llanish tartibi qat'iy

Alohida xususiyatlarni qanday tartibda yozsangiz ham, brauzer ularni doim bitta tartibda qo'llaydi:

  1. translate
  2. rotate
  3. scale
  4. Keyin transform dagi funksiyalar (agar bo'lsa).

Tekshirdik: rotate: 90deg; translate: 100px deb yozdik — rotate birinchi yozilgan bo'lsa ham, element 100 piksel o'ngga ketdi. Ya'ni yuqoridagi "avval translate" qoidasi alohida xususiyatlarda o'z-o'zidan bajariladi.

Yana bir qiziq fakt: DevTools'ning Computed bo'limida bunday elementning transform qiymati none bo'lib qoladi. Uchta alohida xususiyat transform ni to'ldirmaydi — ular o'z nomi bilan alohida turadi.

6.3 Nega qulay: bir-birini o'chirmaydi

«Bahor» muhriga qaytamiz. U rotate(-12deg) bilan burilgan. Endi sichqoncha kelganda muhrni 10 foiz kattalashtirmoqchimiz:

css
.yangi::before {
  transform: rotate(-12deg);
}

/* ❌ Burilish yo'qoladi */
.yangi:hover::before {
  transform: scale(1.1);
}

transform — bitta xususiyat. Hover qoidasi uning butun qiymatini almashtiradi (Kaskad): rotate(-12deg) yo'qoladi, muhr to'g'rilanib kattalashadi. Tuzatish uchun transform: rotate(-12deg) scale(1.1) deb eski qiymatni takrorlash kerak edi.

Alohida xususiyatlar bilan har biri o'z "uyasida" yashaydi:

css
.yangi::before {
  rotate: -12deg;
}

/* ✅ Faqat kattalik o'zgaradi, burilish qoladi */
.yangi:hover::before {
  scale: 1.1;
}

Keyingi darslarda bu yana foydali bo'ladi: Transition va animatsiyalarda har bir xususiyatni alohida boshqarish mumkin.

Qaysi birini ishlatish kerak? Oddiy hollarda — alohida xususiyatlar: o'qish oson, bir-birini o'chirmaydi. Bir nechta siljish yoki skew kerak bo'lsa, yoki tartibni o'zingiz belgilamoqchi bo'lsangiz — transform. Eski kodda asosan transform ni uchratasiz, shuning uchun ikkalasini ham o'qiy olish kerak.

Tekshirib ko'ring: Elementda scale: 2 va translate: 50px bor. U ekranda necha piksel o'ngga siljiydi — 50 mi yoki 100 mi?

Javob
  1. Alohida xususiyatlarda translate doim birinchi qo'llanadi — scale hali ta'sir qilmagan tizimda. «Tartib muhim» bo'limidagi scale(2) translateX(50px) bilan solishtiring: u yerda scale birinchi turgani uchun 100 edi.

7. transform-origin: qaysi nuqta atrofida

rotate va scale qandaydir nuqta atrofida ishlaydi. Odatda bu — elementning markazi. Uni transform-origin xususiyati o'zgartiradi. Eshikni eslang: u o'rtasidan emas, oshig'i (lo'la) atrofida aylanadi. transform-origin — "lo'la qayerda".

Qiymat — ikki koordinata: gorizontal va vertikal.

Yozuv Nuqta
transform-origin: center (odatiy, 50% 50%) Markaz
transform-origin: top left yoki 0 0 Chap yuqori burchak
transform-origin: bottom right O'ng pastki burchak
transform-origin: 20px 100% Chapdan 20 piksel, pastki chet

Uchta bir xil kvadratni 20 gradusga buramiz, faqat nuqtasi har xil. Qizg'ish doiracha — transform-origin joyi:

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --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: 2.5rem 1rem;
  }
  .joy {
    position: relative;
    width: 5rem;
    height: 5rem;
    margin-inline: auto;
    outline: 2px dashed var(--rang-ikkinchi);
  }
  .kvadrat {
    height: 100%;
    background-color: var(--rang-asosiy);
    opacity: 0.85;
    rotate: 20deg;
  }
  .b { transform-origin: top left; }
  .c { transform-origin: bottom right; }
  .nuqta {
    position: absolute;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background-color: var(--rang-urgu);
    translate: -50% -50%;
  }
  .n1 { left: 50%; top: 50%; }
  .n2 { left: 0; top: 0; }
  .n3 { left: 100%; top: 100%; }
  p {
    margin: 2rem 0 0;
    text-align: center;
    font-size: 0.8rem;
  }
</style>
<div class="uchta">
  <div>
    <div class="joy">
      <div class="kvadrat"></div><span class="nuqta n1"></span>
    </div>
    <p><code>center</code></p>
  </div>
  <div>
    <div class="joy">
      <div class="kvadrat b"></div><span class="nuqta n2"></span>
    </div>
    <p><code>top left</code></p>
  </div>
  <div>
    <div class="joy">
      <div class="kvadrat c"></div><span class="nuqta n3"></span>
    </div>
    <p><code>bottom right</code></p>
  </div>
</div>

Nimaga qarang: uchala kvadrat bir xil 20 gradus burilgan, lekin har xil joyga "osilgan". Doiracha turgan nuqta qimirlamadi — kvadrat aynan uning atrofida aylandi. Doirachalarni translate: -50% -50% o'z markazi bilan burchakka qo'ydi — «Foiz — elementning o'z o'lchamidan» bo'limidagi hiyla.

transform-origin scale ga ham ta'sir qiladi. Menyu ochilganda tepadan pastga "tushib chiqishi" uchun transform-origin: top va scaleY birga ishlatiladi — buni @keyframes darsida ko'rasiz.

Maslahat: Chrome DevTools Styles panelida burchak qiymati (20deg) yonida kichik soat belgisi chiqadi. Uni bossangiz, burchakni sichqoncha bilan aylantirib tanlaysiz — natija darhol sahifada ko'rinadi.

8. matrix() — brauzerning o'z tili

Brauzer hamma 2D transformni oxir-oqibat bitta matritsa (matrix) ga — oltita sondan iborat jadvalga aylantiradi. DevTools'da Computed bo'limini ochsangiz, rotate(45deg) o'rniga shuni ko'rasiz:

text
matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0)

Buni Chrome'da transform: rotate(45deg) uchun oldik. Oltita son: dastlabki to'rttasi burish, kattalashtirish va qiyshaytirishni birga ifodalaydi, oxirgi ikkitasi — X va Y bo'yicha siljish (piksel). Masalan, translateY(-20px) uchun Chrome matrix(1, 0, 0, 1, 0, -20) ko'rsatdi: 1 lar "o'zgarishsiz", oxirida −20 — siljish.

matrix() ni qo'lda yozish shart emas va tavsiya ham etilmaydi — rotate(45deg) ancha tushunarli. Uni bilish ikki joyda kerak: DevTools'da Computed qiymatini o'qiganda va JavaScript'da transformni o'qiganda (09-qismda). "Bu g'alati sonlar qayerdan chiqdi?" deb qo'rqmang — bu shunchaki sizning funksiyalaringizning brauzer tilidagi yozuvi.

9. Transformning yon ta'sirlari

Transform "faqat chizishni o'zgartiradi" — lekin to'rtta joyda layout va boshqa elementlarga ta'sir qiladi. Ularni bilmasangiz, "sehrli" xatolarga duch kelasiz.

9.1 Inline element transformlanmaydi

span, a, strong kabi satr ichidagi elementlar odatda display: inline (display). Transform ularga ishlamaydi:

html
<style>
  :root { --rang-urgu: #b4461a; }
  body { font-family: system-ui, sans-serif; }
  .narx {
    color: var(--rang-urgu);
    font-weight: bold;
    rotate: -8deg;
  }
  p:last-child .narx {
    display: inline-block;
  }
</style>
<p>❌ Bugun osh — <span class="narx">35 000 so'm</span>!</p>
<p>✅ Bugun osh — <span class="narx">35 000 so'm</span>!</p>

Nimaga qarang: birinchi qatorda narx to'g'ri turibdi — rotate e'tiborsiz qoldi. Ikkinchi qatorda display: inline-block qo'shildi va narx qiyshaydi. Chrome'da tekshirdik: inline span ga translate(50px) ham berdik — DevTools Computed'da transform qiymati yozilgan, lekin element bir piksel ham siljimagan.

Sababi: inline element bir nechta qatorga bo'linishi mumkin. Ikki qatorga bo'lingan narxni "burish" nima degani? Brauzer bu savolga javob bermaydi — shunchaki transformni qo'llamaydi. Tuzatish: display: inline-block yoki block. Flex va grid bolalari esa o'z-o'zidan blok bo'ladi — ularda muammo yo'q.

9.2 Containing block va stacking context

Ikkalasini 05-qismda ko'rgan edik, endi sababini to'liq bilamiz:

  • Containing block. transform (va translate, rotate, scale) none bo'lmasa, element absolute bolalari uchun containing block bo'ladi (position). Ehtiyot bo'ling: faqat hover'da transform oladigan kartada absolute bola hover paytida boshqa containing block'ga "ko'chib" qolishi mumkin. Shuning uchun kartaga position: relative ni doim yozamiz. fixed bolalar uchun esa tuzoq: ular oynaga emas, transformli ajdodga yopishadi (fixed va sticky).
  • Stacking context. Transformli element o'z qatlamini yaratadi (z-index). Uning ichidagi z-index: 9999 tashqaridagi elementlar bilan "raqobatlasha" olmaydi.

Hatto translate: 0 ham — ko'rinishda hech narsa qilmasa ham — ikkala ta'sirni yaratadi. fixed va sticky darsidagi transform: translate(0) misoli aynan shu edi. Faqat none hech narsa yaratmaydi.

9.3 Transform skroll yaratishi mumkin

Transform layoutni o'zgartirmaydi, lekin sahifaning skroll maydoniga ta'sir qiladi. 800 pikselli oynada elementni translate: 900px bilan o'ngga chiqardik. Chrome'da sahifa eni 1000 piksel bo'ldi — pastda gorizontal skroll paydo bo'ldi.

Ko'p uchraydigan holat: "o'ngdan uchib kiradigan" element boshida translateX(100%) bilan ekrandan tashqarida turadi. Telefonda butun sahifa yon tomonga "tebranadi". Tuzatish: otasiga overflow: clip (Overflow) yoki elementni shunday joyga qo'yingki, u chetdan chiqmasin.

10. «Bahor» menyusi: hammasi birga

Endi menyu kartalariga uchta narsa qo'shamiz:

  1. Aksiyadagi taomga burchakda qiyshiq lenta — rotate va overflow: clip.
  2. Sichqoncha kelganda karta 6 piksel ko'tariladi — translate.
  3. "Stolni band qilish" tugmasi bosilganda biroz kichrayadi — scale.

Holat pseudo-klasslari darsida "tugma bosilganda botib ketgandek ko'rinishi :active dan keladi" degan edik. Endi o'sha "botish" ni yasaymiz.

html
<style>
  :root {
    --rang-asosiy: #2f6b3a;
    --rang-urgu: #b4461a;
    --rang-fon: #fffaf0;
    --rang-matn: #1f2a24;
  }
  body {
    font-family: system-ui, sans-serif;
    color: var(--rang-matn);
  }
  ul {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
    gap: 1rem;
    padding: 0;
    list-style: none;
  }
  li { display: grid; }
  .taom-karta {
    position: relative;
    overflow: clip;
    padding: 0.75rem 1rem;
    border: 2px solid var(--rang-asosiy);
    border-radius: 0.5rem;
    background-color: var(--rang-fon);
  }
  .taom-nomi { margin: 0; }
  .narx { color: var(--rang-urgu); font-weight: bold; }
  .aksiya {
    position: absolute;
    top: 0.9rem;
    right: -2.25rem;
    width: 8rem;
    margin: 0;
    padding-block: 0.125rem;
    background-color: var(--rang-urgu);
    color: var(--rang-fon);
    font-size: 0.8rem;
    font-weight: bold;
    text-align: center;
    rotate: 45deg;
  }
  .bron-havola {
    display: inline-block;
    padding: 0.75rem 1.25rem;
    border-radius: 0.5rem;
    background-color: var(--rang-asosiy);
    color: var(--rang-fon);
    text-decoration: none;
  }
  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
    li:hover > .taom-karta {
      translate: 0 -6px;
      box-shadow: 0 6px 12px rgb(0 0 0 / 0.15);
    }
  }
  @media (prefers-reduced-motion: no-preference) {
    .bron-havola:active {
      scale: 0.96;
    }
  }
</style>
<ul>
  <li>
    <article class="taom-karta">
      <h3 class="taom-nomi">Osh</h3>
      <p class="narx">35 000 so'm</p>
    </article>
  </li>
  <li>
    <article class="taom-karta">
      <p class="aksiya">−10%</p>
      <h3 class="taom-nomi">Lag'mon</h3>
      <p class="narx">28 000 so'm</p>
    </article>
  </li>
  <li>
    <article class="taom-karta">
      <h3 class="taom-nomi">Manti</h3>
      <p class="narx">30 000 so'm</p>
    </article>
  </li>
</ul>
<a class="bron-havola" href="#">Stolni band qilish</a>

Nimaga qarang: "Lag'mon" kartasining o'ng yuqori burchagida qizg'ish lenta 45 gradus qiyshaygan. Uning chiqib turgan uchlarini overflow: clip kartaning yumaloq chegarasi bo'ylab kesdi. Sichqonchani kartalar ustiga olib boring — har biri 6 piksel ko'tarilib, soya oladi, qo'shnilari esa joyida. Tugmani bosib turing — u biroz kichrayadi.

Kodda uchta qaror bor:

  • Hover li da, harakat kartada. Nega .taom-karta:hover emas? Buni "Ko'p uchraydigan xatolar" bo'limida ko'ramiz — bu titrash tuzog'ining tuzatilgan shakli.
  • Harakat prefers-reduced-motion: no-preference ichida. Foydalanuvchi afzalliklari darsidagi no-motion-first tamoyili: sakrash ham harakat. Harakatni kamaytirishni yoqqan odamda karta faqat soyasiz qoladi — lekin hover holatini tugmalardan biladi.
  • Hozircha sakrab o'zgaradi. Karta bir zumda ko'tariladi, silliq emas. Silliq o'tishni keyingi darslardan birida — Transition da qo'shamiz.

11. Ko'p uchraydigan xatolar

11.1 Hover titraydi

Eng mashhur transform xatosi:

css
/* ❌ Karta o'zi hover'ni "qochiradi" */
.taom-karta:hover {
  translate: 0 -8px;
}

Kursor kartaning pastki chetida turibdi. Karta 8 piksel ko'tariladi — endi kursor ostida karta yo'q, uning pastki cheti kursordan tepada. Brauzer transformdan keyingi joyni tekshiradi: "sichqoncha kartada emas" — hover o'chadi, karta tushadi. Tushgan karta yana kursor ostida — yana ko'tariladi.

Chrome'da tekshirdik: kursor kartaning pastki 8 pikseli ichida bo'lsa, karta ko'tarilmay qoladi — sichqoncha har qimirlaganda hover yoqilib-o'chadi. Foydalanuvchi buni titrash sifatida ko'radi.

Tuzatish: hover'ni qimirlamaydigan otaga bering, transformni esa bolaga. «Bahor» menyusidagi li:hover > .taom-karta aynan shunday. Tekshirdik: o'sha 8 piksellik chiziqda ham karta barqaror ko'tarilib turdi.

11.2 Ikkinchi transform birinchisini o'chiradi

transform: rotate(-12deg) bor elementga hover'da transform: scale(1.1) — burilish yo'qoladi. "Alohida xususiyatlar" bo'limidagi yechim: rotate va scale ni alohida yozing, yoki transform da ikkala funksiyani takrorlang.

11.3 Inline elementga transform

span yoki a ga rotate yozdingiz — hech narsa o'zgarmadi, xato xabari ham yo'q. Tuzatish: display: inline-block.

11.4 Transform — "oddiy stil" deb o'ylash

Sahifa o'ramiga "shunchaki" transform qo'shildi — va fixed chat tugmasi sahifa bilan birga suriladi, modal oyna z-index: 9999 bo'lsa ham boshqa narsa ostida qoladi. Tuzatish: fixed va baland z-index li elementlarni transformli ajdoddan tashqariga chiqaring. Muammo chiqsa, DevTools'da ajdodlarda transform, translate, rotate, scale qidiring.

12. Mashqlar

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

1-mashq (oson): So'zdan transformga

Har bir tavsif uchun transform qiymatini yozing, keyin xuddi shuni alohida xususiyat bilan yozing:

  1. Tugma 2 piksel pastga tushsin.
  2. "Keyingi" strelkasi (→) chapga qarasin — "Oldingi" uchun.
  3. Rasm 5 foiz kattalashsin.
  4. Belgi 1/8 aylanaga (45 gradus) soat miliga teskari burilsin.

Ishora: burchakni deg yoki turn bilan yozing; ko'zgu aksi — manfiy scale.

Yechim
# transform Alohida xususiyat
1 translateY(2px) translate: 0 2px
2 scaleX(-1) yoki rotate(180deg) scale: -1 1 yoki rotate: 180deg
3 scale(1.05) scale: 1.05
4 rotate(-45deg) yoki rotate(-0.125turn) rotate: -45deg

2-bandda ikkala javob ham strelkani chapga qaratadi. Farqi — rotate(180deg) strelkani ostin-ustun ham qiladi. → simmetrik bo'lgani uchun farq ko'rinmaydi, lekin ichida matn bo'lsa, rotate uni teskari yozib qo'yadi.

2-mashq (o'rta): Ochiladigan savol belgisi

«Bahor» menyu sahifasida "Taom haqida" savol-javobi details bilan yozilgan (details va summary). Brauzerning uchburchak belgisini o'zingiznikiga almashtiring: summary oldida ▸ belgisi tursin va savol ochilganda u 90 gradus burilib, pastga qarasin.

html
<details>
  <summary>Oshga nima solinadi?</summary>
  <p>Guruch, sabzi, piyoz, go'sht va zira.</p>
</details>

Ishora: brauzer belgisini summary { list-style: none; } olib tashlaydi (Ro'yxatlar stili). Yangi belgini summary::before bilan chizing (Pseudo-elementlar). Ochiq holat — details[open] (Atribut selektorlari). Pseudo-element odatda inline — «Inline element transformlanmaydi» bo'limini eslang.

Yechim
css
summary {
  list-style: none; /* brauzer uchburchagi o'chadi */
}

/* Safari eski belgini alohida yo'l bilan chizadi */
summary::-webkit-details-marker {
  display: none;
}

summary::before {
  content: "▸";
  display: inline-block; /* inline'ga transform ishlamaydi */
  margin-inline-end: 0.5em;
  color: #2f6b3a;
}

details[open] > summary::before {
  rotate: 90deg;
}

Natijasi:

html
<style>
  body { font-family: system-ui, sans-serif; }
  summary {
    list-style: none;
  }
  summary::-webkit-details-marker { display: none; }
  summary::before {
    content: "▸";
    display: inline-block;
    margin-inline-end: 0.5em;
    color: #2f6b3a;
  }
  details[open] > summary::before { rotate: 90deg; }
</style>
<details>
  <summary>Oshga nima solinadi?</summary>
  <p>Guruch, sabzi, piyoz, go'sht va zira.</p>
</details>
<details open>
  <summary>Choy qanday damlanadi?</summary>
  <p>Choynak qaynoq suv bilan chayiladi, keyin choy solinadi.</p>
</details>

Birinchi savol yopiq — belgi o'ngga qaragan. Ikkinchisi ochiq — belgi pastga qaragan. display: inline-block siz ikkala belgi ham o'ngga qarab qolardi: Chrome'da tekshirdik, ::before inline bo'lganda rotate e'tiborsiz qoldi. Belgi markazi atrofida aylanadi — transform-origin ni o'zgartirish shart emas.

3-mashq (qiyin): Stajyorning kartasini tuzating

Stajyor «Bahor» uchun shunday yozdi. Jasur aka ikki shikoyat qildi: "karta pastidan sichqoncha olib borsam, titraydi" va "hover'da «Yangi» muhri to'g'rilanib qoladi".

css
.taom-karta {
  position: relative;
}

.taom-karta:hover {
  translate: 0 -8px;
}

.yangi::before {
  content: "Yangi";
  position: absolute;
  top: 0;
  right: 0;
  transform: translate(30%, -50%) rotate(-12deg);
}

.yangi:hover::before {
  transform: scale(1.1);
}
  1. Har ikki shikoyatning sababini tushuntiring.
  2. Kodni tuzating. Kartalar ul > li ichida turibdi.
  3. Tuzatilgan kodga harakatni kamaytirish sozlamasini hurmat qiladigan shart qo'shing.

Ishora: "Ko'p uchraydigan xatolar" bo'limidagi birinchi ikki holat. Qo'llanish tartibini "Alohida xususiyatlar" bo'limidan eslang: translate → rotate → scale.

Yechim
  1. Titrash: hover va harakat bitta elementda. Karta ko'tarilgach, pastki 8 piksellik chiziqdagi kursor kartadan "tushib qoladi", hover o'chadi, karta tushadi — va yana boshidan. Muhr to'g'rilanishi: hover qoidasi transform ning butun qiymatini scale(1.1) ga almashtirdi — translate ham, rotate ham yo'qoldi.

2–3. Tuzatilgani:

css
.taom-karta {
  position: relative;
}

.yangi::before {
  content: "Yangi";
  position: absolute;
  top: 0;
  right: 0;
  translate: 30% -50%;
  rotate: -12deg;
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  li:hover > .taom-karta {
    translate: 0 -8px;
  }

  li:hover > .yangi::before {
    scale: 1.1;
  }
}
  • Hover endi li da — u qimirlamaydi, titrash yo'q.
  • Muhrda uchta alohida xususiyat: hover faqat scale ni qo'shadi, translate va rotate joyida qoladi. Brauzer ularni to'g'ri tartibda qo'llaydi — avval siljish, keyin burish, keyin kattalashtirish. Bu aynan eski translate(30%, -50%) rotate(-12deg) tartibi.
  • (hover: hover) — faqat sichqonchali qurilmada (Foydalanuvchi afzalliklari). Telefonda "yopishib qolgan" hover bo'lmaydi.

4-mashq: Portfolio qadami — "boshqa sayt" strelkasi harakatlansin

Yakuniy loyiha darsida boshqa saytga olib boradigan havolalar oxiriga ↗ belgisi qo'shilgan edi:

css
a[href^="https://"]::after {
  content: " ↗";
  content: " ↗" / ", boshqa sayt";
}

Endi sichqoncha havolaga kelganda strelka biroz o'ngga va tepaga — o'zi ko'rsatgan tomonga — "intilsin".

  1. Strelkaga transform ishlashi uchun kerakli o'zgarishni qiling. Strelka va so'z orasidagi bo'sh joy saqlansin.
  2. Hover'da strelkani 0.125em o'ngga va 0.125em tepaga siljiting. Faqat sichqonchali qurilmada va harakat taqiqlanmagan bo'lsa.
  3. Chrome'da tekshiring: strelka ostida chiziq qoldimi? Ctrl + P bosing — chop etishda havola manzili to'g'ri chiqyaptimi?

Ishora: «Inline element transformlanmaydi» bo'limi. Bo'sh joy haqida — inline-block ichidagi boshlang'ich bo'sh joy qatorning boshi kabi "yutiladi".

Yechim

"3. Umumiy" bo'limidagi qoida almashadi:

css
/* Boshqa saytga havola: ko'z uchun belgi, quloq uchun so'z
   (Pseudo-elementlar va 2D transformlar darslari) */
a[href^="https://"]::after {
  content: "↗";
  content: "↗" / ", boshqa sayt";
  display: inline-block; /* inline'ga transform ishlamaydi */
  margin-inline-start: 0.25em; /* bo'sh joy o'rniga */
}

"6. Afzalliklar va qurilma" bo'limiga, mavjud @media (hover: hover) blokidan keyin:

css
/* Harakat faqat ruxsat bo'lsa (Foydalanuvchi afzalliklari va 2D
   transformlar darslari) */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  a[href^="https://"]:hover::after {
    translate: 0.125em -0.125em;
  }
}

"7. Chop etish" dagi qoidaga ikki qator — qog'ozda manzil oddiy matn bo'lib qatorga bo'linsin:

css
@media print {
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    display: inline;
    margin: 0;
  }
}

Chrome'da tekshirdik:

  • Bo'sh joy. content: " ↗" va inline-block bilan havola 4.4 piksel qisqardi — boshlang'ich bo'sh joy yo'qoldi, strelka so'zga yopishdi. Shuning uchun bo'sh joy margin-inline-start ga o'tdi.
  • Chiziq. inline-block strelka ostida havola chizig'i yo'q — chiziq faqat so'z ostida. Bu hatto chiroyliroq: strelka belgi, matn emas.
  • Chop etish. display: inline qaytmasa, uzun manzil bitta "qutiga" qamalib, qatorga sig'may qolishi mumkin edi.

Qolgan hamma narsa — content dagi ekran o'quvchi matni, rang, fokus halqasi — o'zgarmadi. Faylni saqlab, npm run check bilan tekshiring.

13. Real ishda

  • Hover va bosilish effektlari. Deyarli har bir zamonaviy saytda kartalar ko'tariladi, tugmalar bosilganda kichrayadi, strelkalar suriladi — hammasi translate va scale. Katta kompaniyalarning dizayn tizimlarida bu qiymatlar ham token sifatida yoziladi (Dizayn tokenlari).
  • Ikonkalar. Bitta strelka ikonkasi rotate bilan to'rt tomonga qaratiladi — to'rtta fayl o'rniga bitta.
  • Markazlash. translate: -50% -50% modal oynalar, tooltiplar va rasm ustidagi belgilarda hamon keng ishlatiladi.
  • Animatsiya asosi. Keyingi darslardagi transition va animatsiyalarning 90 foizi aynan transform va opacity ni o'zgartiradi — chunki ular layoutni qayta hisoblatmaydi (Rendering va samaradorlik).
  • Intervyuda so'raladi: "transform: translate() va position: relative + top ning farqi nima?", "Nega animatsiyada left emas, transform ishlatiladi?", "Transform nega fixed elementni buzadi?" Endi uchalasiga ham javob bera olasiz.

Xulosa

  • transform elementni chizishda o'zgartiradi — layoutdagi joyi saqlanadi, qo'shnilar surilmaydi.
  • translate — siljitish (foizi o'z o'lchamidan), rotate — burish (deg, turn), scale — kattalashtirish, skew — qiyshaytirish.
  • transform dagi funksiyalar tartibi muhim: avval translate, keyin rotate va scale.
  • Alohida translate, rotate, scale xususiyatlari bir-birini o'chirmaydi va doim shu tartibda qo'llanadi.
  • transform-origin — aylanish va kattalashish nuqtasi; odatda markaz.
  • Yon ta'sirlar: inline'ga ishlamaydi, containing block va stacking context yaratadi, skroll qo'shishi mumkin, hover'ni "qochiradi".

Keyingi dars: 3D transformlar va perspektiva — elementni uch o'lchamli fazoda aylantirib, ag'dariladigan karta yasaymiz.

Manbalar

  • MDN: "transform", "translate", "rotate", "scale", "transform-origin", "Using CSS transforms" — developer.mozilla.org
  • W3C: "CSS Transforms Module Level 1" va "Level 2" (alohida xususiyatlar) — w3.org/TR/css-transforms-1, w3.org/TR/css-transforms-2
  • web.dev: "Learn CSS — Functions" (transform funksiyalari) — web.dev/learn/css
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS transform: 2D transformlar — siljitish, burish va kattalashtirish — IlmHamroh