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

Sass/SCSS 2: mixin, funksiya, map va boshqaruv

Qisqacha: Sass'ning asosiy kuchi — takroriy CSS'ni avtomatik yasash. Mixin (@mixin) qoidalar to'plamini saqlaydi, @include uni kerakli joyga qo'yadi; @content bilan breakpoint mixin yoziladi. Funksiya (@function) qiymat hisoblaydi (math.div, color.adjust), map esa nom–qiymat juftlarini saqlaydi va @each sikli ulardan o'nlab qoida yoki CSS o'zgaruvchisini yasaydi. Selektorlarni kutilmaganda ko'paytiradigan @extend o'rniga mixin ishlating.

Bu darsda

  • @mixin va @include bilan argumentli, standart qiymatli qoida to'plamlarini yozasiz.
  • @content bilan breakpoint mixin yasaysiz va uni «Bahor»ning ITCSS "Tools" qatlamiga qo'yasiz.
  • @extend va placeholder qanday ishlashini, nega xavfli ekanini tushuntira olasiz.
  • @function, sass:math, sass:color va sass:map modullaridan foydalanasiz.
  • @each, @for, @if va @error bilan CSS'ni avtomatik yasaysiz va bugun Sass qachon kerakligini asoslaysiz.

Oldin bilishingiz kerak: Sass/SCSS 1, Fluid tipografiya, CSS metodologiyalari.

1. Nega bu kerak?

Sass/SCSS 1 darsida o'zgaruvchi, nesting va modullarni ko'rdik. Ular yozishni qulay qildi, lekin kod miqdorini kamaytirmadi. «Bahor»da esa hali ko'p takror bor:

  • Tugma ko'rinishi ikki joyda: .bron-havola va forma tugmasi. Faqat rangi farq qiladi.
  • Har komponentda @media (width >= 40rem) — o'nlab marta.
  • Taom kartasining to'rtta modifikatori (yangi, mashhur, achchiq, tugadi) — deyarli bir xil to'rtta qoida.
  • Fluid tipografiya darsida clamp() formulalarini kalkulyatorda hisoblagan edik: 0.9511rem + 0.2174vw. Bitta raqamda adashsangiz, shrift sakraydi.

Bularning hammasini qolip bilan yechsa bo'ladi. Non yopuvchi har nonni qo'lda shakllantirmaydi — naqshli qolipni bosadi va bir xil nonlar chiqadi. Qolipni bir marta yasaysiz, keyin xohlagancha ishlatasiz. Sass'dagi mixin, funksiya va sikllar — shunday qoliplar.

2. Mixin: qoidalar to'plami

2.1 @mixin va @include

Mixin — nomi bor deklaratsiyalar to'plami. @mixin bilan e'lon qilinadi, @include bilan kerakli joyga qo'yiladi:

scss
@mixin tugma($fon, $matn: #fffaf0) {
  padding: 0.5rem 1.5rem;
  border: 0;
  border-radius: 0.5rem;
  background-color: $fon;
  color: $matn;
}

.bron-havola {
  @include tugma(#2f6b3a);
}

.aksiya {
  @include tugma($fon: #b4461a);
}

Natija:

css
.bron-havola {
  padding: 0.5rem 1.5rem;
  border: 0;
  border-radius: 0.5rem;
  background-color: #2f6b3a;
  color: #fffaf0;
}

.aksiya {
  padding: 0.5rem 1.5rem;
  border: 0;
  border-radius: 0.5rem;
  background-color: #b4461a;
  color: #fffaf0;
}

Tafsilotlar:

  • $fon va $matn — argumentlar, mixin'ga beriladigan qiymatlar. Qavsda nom bilan yoziladi.
  • $matn: #fffaf0 — standart qiymat: berilmasa, shu olinadi. Ikkala qoidada ham matn qaymoq rangda chiqdi.
  • tugma($fon: #b4461a) — argumentni nomi bilan berish. Argument ko'p bo'lsa, tartibni eslab o'tirmaysiz.

Majburiy argument berilmasa, Sass to'xtaydi:

text
Error: Missing argument $fon.
    ╷
1   │ @mixin tugma($fon) {
    │        ━━━━━━━━━━━ declaration
... │
5   │   @include tugma;
    │   ^^^^^^^^^^^^^^ invocation
    ╵
  x2.scss 5:3  tugma()
  x2.scss 5:3  root stylesheet

Tarjimasi: "$fon argumenti yetishmayapti." Sass ikki joyni ko'rsatadi: declaration — mixin qayerda e'lon qilingan, invocation — qayerda chaqirilgan.

2.2 Mixin natijani qisqartirmaydi

Natijaga qarang: padding, border, border-radius ikki marta yozildi. Mixin manba kodni qisqartiradi, CSS faylni emas — har @include to'plamni to'liq nusxalaydi. 50 ta tugmada 50 nusxa. Server fayllarni yuborishdan oldin siqadi (gzip, Brotli usullari — CSS yuklash samaradorligi darsida) va takrorni yaxshi kichraytiradi, lekin mixin'ni katta to'plamlar uchun ehtiyot bilan ishlating.

Ko'p holatda boshqa yo'l yaxshiroq: bitta umumiy class va CSS o'zgaruvchisi (CSS o'zgaruvchilari 2 darsidagi --tugma-fon). Shunda qoida bitta, faqat rang o'zgaradi. Mixin — rang emas, tuzilma o'zgarganda kerak: masalan, media query.

2.3 @content — breakpoint mixin

@content — "@include qilgan joy bergan blokni shu yerga qo'y". Mixin qobiq bo'ladi, ichini chaqiruvchi to'ldiradi:

scss
@use "sass:map";

$ekranlar: (
  "planshet": 40rem,
  "kompyuter": 64rem,
);

@mixin ekran($nom) {
  @media (width >= map.get($ekranlar, $nom)) {
    @content;
  }
}

.taom-karta {
  padding: 1rem;

  @include ekran("planshet") {
    padding: 1.5rem;
  }
}

Natija:

css
.taom-karta {
  padding: 1rem;
}
@media (width >= 40rem) {
  .taom-karta {
    padding: 1.5rem;
  }
}

$ekranlar — map ("xarita"), nom–qiymat juftlari. map.get($ekranlar, "planshet") → 40rem. Map'larni pastda to'liq ko'ramiz.

Nega bu yaxshi? Breakpoint'lar Media queries darsidagi 40rem va 64rem — endi bitta joyda. Kod o'qilishi ham ma'noga yaqin: "planshet va kattaroqda". Bootstrap'ning media-breakpoint-up(md) mixin'i aynan shu g'oya.

Mixin blok kutmasa-yu, siz blok bersangiz:

text
Error: Mixin doesn't accept a content block.

Tarjimasi: "Mixin kontent blokini qabul qilmaydi" — mixin ichida @content yo'q.

2.4 Mixin'lar qayerda yashaydi

CSS metodologiyalari darsida «Bahor»ni ITCSS qatlamlari bo'yicha bo'lganda Tools qatlami bo'sh qolgan edi: "oddiy CSS'da mixin yo'q". Endi u to'ladi. Sass versiyasida bu qatlam — _vositalar.scss: mixin va funksiyalar. U o'zi hech qanday CSS chiqarmaydi, faqat boshqa fayllarga qolip beradi.

text
scss/
├── _ranglar.scss     ← Settings: palitra map'i
├── _vositalar.scss   ← Tools: mixin va funksiyalar
├── _tokenlar.scss    ← :root o'zgaruvchilari
├── _karta.scss       ← Components
└── asosiy.scss       ← kirish

Fayllar to'liq holda darsning oxirgi bo'limlarida.

Tekshirib ko'ring: @include ekran("planshet") { ... } ni 20 ta komponentda ishlatdingiz. Dizayner planshet chegarasini 48rem ga o'zgartirdi. Nechta joyni tahrirlaysiz?

Javob

Bitta: $ekranlar map'idagi "planshet": 40rem qatorini. Qayta kompilyatsiyadan keyin 20 ta @media ning hammasi 48rem bo'ladi. Oddiy CSS'da 20 ta @media (width >= 40rem) ni qidirib, har birini almashtirish kerak bo'lardi.

3. @extend va placeholder

3.1 Qanday ishlaydi

@extend boshqacha yo'l tutadi: deklaratsiyalarni nusxalamaydi, selektorni boshqa qoidaga qo'shadi. ".mashhur ham .taom-karta ning hamma qoidalarini olsin":

scss
.taom-karta {
  padding: 1rem;
  border: 2px solid #2f6b3a;
}

.menyu .taom-karta,
.aksiya .taom-karta {
  margin-block: 1rem;
}

.mashhur {
  @extend .taom-karta;
  border-color: #b4461a;
}

Natija:

css
.taom-karta, .mashhur {
  padding: 1rem;
  border: 2px solid #2f6b3a;
}

.menyu .taom-karta, .menyu .mashhur,
.aksiya .taom-karta,
.aksiya .mashhur {
  margin-block: 1rem;
}

.mashhur {
  border-color: #b4461a;
}

Birinchi qoidada kutilgani bo'ldi. Lekin ikkinchisiga qarang: .taom-karta uchragan har selektorga .mashhur ham qo'shildi — biz so'ramagan joylarga ham. Katta loyihada bitta @extend yuzlab selektorni ko'paytirib, CSS'ni shishirib yuborishi va kaskadni chalkashtirishi mumkin. Qoida CSS'da qayerga tushganini ham oldindan aytish qiyin: .mashhur endi .taom-karta turgan joyda, ya'ni fayl boshida.

3.2 Placeholder %

Bu xavfni kamaytiradigan maxsus selektor bor — placeholder, % bilan boshlanadi. U o'zi CSS'ga chiqmaydi, faqat @extend uchun yashaydi:

scss
%karta-asos {
  padding: 1rem;
  border-radius: 0.5rem;
}

.taom-karta {
  @extend %karta-asos;
}

.bron-havola {
  @extend %karta-asos;
}

Natija:

css
.bron-havola, .taom-karta {
  padding: 1rem;
  border-radius: 0.5rem;
}

%karta-asos natijada yo'q, boshqa selektorlarga "yopishib" qolmaydi.

3.3 Media query bilan ishlamaydi

scss
.narx {
  @media (width >= 40rem) {
    @extend .aksiya;
  }
}

.aksiya {
  color: #b4461a;
}
text
Error: You may not @extend selectors across media queries.

Tarjimasi: "Selektorlarni media query'lar orasida @extend qilib bo'lmaydi." Sass .narx ni @media dan tashqaridagi .aksiya qoidasiga qo'sha olmaydi — u faqat planshetda ishlashi kerak edi.

Amaliy qoida: @extend o'rniga mixin. Ko'p jamoalar @extend ni linter (kodni avtomatik tekshiradigan dastur, Stylelint va Prettier darsida) bilan taqiqlaydi. Uni eski kodda uchratasiz — endi nima qilishini bilasiz.

Tekshirib ko'ring: .mashhur { @extend .taom-karta; } va .mashhur { @include karta; } — CSS natijasida nima farq qiladi?

Javob

@extend deklaratsiyalarni nusxalamaydi — .mashhur ni .taom-karta turgan har bir selektorga vergul bilan qo'shadi, hatto kutilmagan joylarga ham. @include esa mixin ichidagi deklaratsiyalarni aynan .mashhur qoidasiga nusxalaydi — boshqa hech qayerga tegmaydi. Shuning uchun mixin'ning natijasini oldindan aytish oson.

4. Funksiyalar

4.1 @function va @return

Mixin — deklaratsiyalar to'plami. Funksiya esa bitta qiymat qaytaradi. «Bahor» dizayneri o'lchamlarni pikselda beradi, biz esa rem da yozamiz (O'lcham birliklari). Har safar 16 ga bo'lish o'rniga:

scss
@use "sass:math";

@function rem($px) {
  @return math.div($px, 16px) * 1rem;
}

h1 {
  font-size: rem(40px);
  margin-block: rem(24px);
}

Natija:

css
h1 {
  font-size: 2.5rem;
  margin-block: 1.5rem;
}

math.div(40px, 16px) → 2.5 (piksel pikselga bo'linsa, birlik qisqaradi), * 1rem → 2.5rem.

4.2 Nega / emas

Eski kodda bo'lish / bilan yozilgan. Lekin CSS'da / bo'lish emas, ajratgich: font: 16px/1.5 serif (o'lcham va qator balandligi), grid-area: 1 / 3. Sass qaysi biri ekanini taxmin qilishga majbur edi. Endi u ogohlantiradi:

text
DEPRECATION WARNING [slash-div]: Using / for division outside of calc() is deprecated and will be removed in Dart Sass 2.0.0.

Recommendation: math.div(40px, 16px) or calc(40px / 16px)

Tarjimasi: "calc() dan tashqarida bo'lish uchun / ishlatish eskirgan va Dart Sass 2.0.0 da olib tashlanadi. Tavsiya: math.div(40px, 16px) yoki calc(40px / 16px)." Shu faylda font: 16px/1.5 serif esa o'zgarmasdan CSS'ga o'tdi — Sass uni to'g'ri tanidi.

4.3 O'rnatilgan modullar

Sass'ning tayyor funksiyalari modullarga bo'lingan va @use "sass:..." bilan ulanadi:

Modul Nima uchun Misol
sass:math Hisob math.div, math.round, math.pow
sass:color Rang color.adjust, color.mix
sass:map Map map.get, map.has-key, map.keys
sass:string Matn string.to-upper-case

Eski kodda bu funksiyalar modulsiz, "global" nomlar bilan yozilgan: map-get(), darken(). Ular hali ishlaydi, lekin ogohlantiradi:

text
DEPRECATION WARNING [global-builtin]: Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0.
Use map.get instead.

Tarjimasi: "Global o'rnatilgan funksiyalar eskirgan va Dart Sass 3.0.0 da olib tashlanadi. Uning o'rniga map.get ni ishlating."

4.4 sass:color va brauzerning o'z ranglari

scss
@use "sass:color";

$asosiy: #2f6b3a;

.bron-havola {
  background-color: $asosiy;

  &:hover {
    background-color: color.adjust($asosiy, $lightness: -10%);
  }
}

.taom-karta {
  background-color: color.mix($asosiy, #fffaf0, 8%);
}

Natija (Sass 1.105.1):

text
.bron-havola {
  background-color: #2f6b3a;
}
.bron-havola:hover {
  background-color: rgb(12.3274764451%, 28.0646804176%, 15.2126305067%);
}

.taom-karta {
  background-color: rgb(93.4745098039%, 93.5529411765%, 88.4078431373%);
}
  • color.adjust($asosiy, $lightness: -10%) — yorug'likni 10 foizga kamaytiradi: to'qroq yashil.
  • color.mix(a, b, 8%) — 8% yashil va 92% qaymoq aralashmasi.
  • Natija — foizli rgb(). Bu to'g'ri CSS rang, faqat o'qishga noqulay. Yangi Sass ranglarni aniqroq hisoblaydi va shunday yozadi.

Lekin Ranglar 3 darsini eslang: brauzerning o'zi ham color-mix(in oklch, ...) va nisbiy ranglar oklch(from ...) ni biladi. Farqi yana o'sha: Sass rangni bir marta, kompilyatsiyada hisoblaydi. Brauzer esa var(--rang-asosiy) o'zgarsa (qorong'i rejim) — hosila rangni qayta hisoblaydi. Portfolio'ning --rang-chegara va --rang-fon-och i shuning uchun color-mix() da. Qoida: rang mavzuga qarab o'zgarsa — brauzer funksiyasi, o'zgarmas palitra yasash — Sass ham bo'ladi.

Tekshirib ko'ring: width: (40px / 16px) * 1rem; ni ko'rdingiz. Nima bo'ladi va qanday tuzatasiz?

Javob

Hozir natija chiqadi (2.5rem), lekin Sass slash-div ogohlantirishini beradi: kelajakdagi Dart Sass 2.0.0 da / bo'lish sifatida ishlamaydi. Tuzatish: @use "sass:math"; va math.div(40px, 16px) * 1rem. Yoki yuqoridagi rem(40px) funksiyasi.

5. Map va sikllar

5.1 Map: nom–qiymat ro'yxati

Map qavs ichida yoziladi, har juft "kalit": qiymat, oxirida vergul:

scss
$ranglar: (
  "asosiy": #2f6b3a,
  "asosiy-toq": #1a5d1a,
  "urgu": #b4461a,
  "fon": #fffaf0,
  "matn": #1f2a24,
  "ikkinchi": #5b6660,
);

Bu — «Bahor» palitrasi (CSS o'zgaruvchilari 1 darsidagi o'sha oltita rang), endi bitta ro'yxatda. sass:map moduli bilan ishlatiladi: map.get($ranglar, "urgu") → #b4461a, map.has-key($ranglar, "urgu") → true, map.keys($ranglar) → hamma nomlar.

5.2 @each — map'dan CSS o'zgaruvchilari

@each — ro'yxat yoki map'ning har elementi uchun blokni takrorlaydi. Palitradan :root o'zgaruvchilarini yasaymiz:

scss
:root {
  @each $nom, $qiymat in $ranglar {
    --rang-#{$nom}: #{$qiymat};
  }
}

Natija:

css
:root {
  --rang-asosiy: #2f6b3a;
  --rang-asosiy-toq: #1a5d1a;
  --rang-urgu: #b4461a;
  --rang-fon: #fffaf0;
  --rang-matn: #1f2a24;
  --rang-ikkinchi: #5b6660;
}

$nom, $qiymat — har aylanishda map'ning navbatdagi kaliti va qiymati. --rang-#{$nom} — interpolyatsiya nom ichida: --rang- + asosiy. Sass/SCSS 1 darsidagi #{} tuzog'i ham shu yerda yechildi: qiymat ham #{$qiymat}.

Bu yondashuvning qiymati: palitra Sass'da bitta joyda, lekin brauzerga CSS o'zgaruvchisi bo'lib boradi. Qorong'i rejim, DevTools, meros — hammasi ishlaydi. Yangi rang qo'shsangiz, map'ga bitta qator yetadi.

5.3 @each — modifikatorlar

Kartaning belgilari:

scss
$belgilar: (
  "yangi": #2f6b3a,
  "mashhur": #b4461a,
  "achchiq": #b4461a,
);

@each $nom, $rang in $belgilar {
  .taom-karta.#{$nom} {
    border-color: $rang;
  }
}

Natija — uchta qoida: .taom-karta.yangi, .taom-karta.mashhur, .taom-karta.achchiq, har biri o'z chegara rangi bilan. Selektor ichida ham interpolyatsiya ishlaydi.

5.4 @for — sonli sikl

@for $i from 1 through 3 — $i 1, 2, 3 qiymatlarini oladi (through — oxirgisi ham kiradi, to bo'lsa — kirmaydi). Sarlavhalar uchun tipografik shkala: har pog'ona oldingisidan 1.25 marta katta (Tipografik shkala darsida chuqur):

scss
@use "sass:math";

@for $i from 1 through 3 {
  h#{$i} {
    font-size: math.pow(1.25, 4 - $i) * 1rem;
  }
}

Natija:

css
h1 {
  font-size: 1.953125rem;
}

h2 {
  font-size: 1.5625rem;
}

h3 {
  font-size: 1.25rem;
}

math.pow(1.25, 3) — 1.25 ni uch marta ko'paytirish: 1.953125. Qo'lda hisoblasangiz, adashish oson; Sass'da — yo'q.

h#{$i} ga qarang: interpolyatsiya selektor nomining bir bo'lagini yasadi — h + 1. 4 - $i esa tartibni teskari qiladi: h1 eng katta pog'onani (uchinchi daraja), h3 eng kichigini (birinchi daraja) oladi.

Tekshirib ko'ring: @for $i from 1 to 3 yozilsa, nechta sarlavha qoidasi chiqadi? @each bilan @for ning farqi nima?

Javob

Ikkita: h1 va h2. Sababi: to oxirgi sonni kiritmaydi — $i faqat 1 va 2 bo'ladi. Aksincha, through 3 ni ham kiritadi. Farqi: @for sonlar ketma-ketligi bo'yicha aylanadi, @each esa tayyor ro'yxat yoki map elementlari bo'yicha: nomlar kerak bo'lsa (asosiy, urgu) — @each, tartib raqami kerak bo'lsa — @for.

5.5 @if va @else — shart

Tugma mixin'ini "aqlli" qilamiz: fon och bo'lsa — matn to'q, to'q bo'lsa — och:

scss
@use "sass:color";

@mixin tugma($fon) {
  padding: 0.5rem 1.5rem;
  border-radius: 0.5rem;
  background-color: $fon;

  @if color.channel($fon, "lightness", $space: hsl) > 60% {
    color: #1f2a24;
  } @else {
    color: #fffaf0;
  }
}

.bron-havola {
  @include tugma(#2f6b3a);
}

.aksiya {
  @include tugma(#fffaf0);
}

Natijada .bron-havola — color: #fffaf0 (to'q yashil fonda qaymoq matn), .aksiya — color: #1f2a24 (qaymoq fonda to'q matn). color.channel(..., "lightness", $space: hsl) — rangning HSL bo'yicha yorug'ligi (Ranglar 1). Bu oddiy qoida, kontrastni kafolatlamaydi — kontrastni baribir o'lchang (CSS'da accessibility).

5.6 @error, @warn, @debug

Mixin'ga noto'g'ri qiymat berilsa, jim buzilishdan ko'ra aniq xato yaxshi. ekran mixin'iga tekshiruv qo'shamiz:

scss
@mixin ekran($nom) {
  @if not map.has-key($ekranlar, $nom) {
    @error "Bunday ekran yo'q: #{$nom}. Bor: #{map.keys($ekranlar)}";
  }

  @media (width >= map.get($ekranlar, $nom)) {
    @content;
  }
}

@include ekran("telefon") yozilsa:

text
Error: "Bunday ekran yo'q: telefon. Bor: planshet, kompyuter"
   ╷
19 │   @include ekran("telefon") {
   │   ^^^^^^^^^^^^^^^^^^^^^^^^^
   ╵
  i1.scss 19:3  root stylesheet

Xato matnini o'zimiz yozdik — o'zbekcha va aniq. Ikki yumshoqroq ko'rsatma ham bor: @warn — ogohlantirish chiqaradi, lekin kompilyatsiya davom etadi. @debug — qiymatni terminalga chiqaradi, tekshirish uchun:

text
i2.scss:11 DEBUG: 24px = 1.5rem
WARNING: rem() px kutadi, keldi: 1.5em
    i2.scss 5:5    rem()
    i2.scss 15:11  root stylesheet

Bu yerda rem() funksiyasiga @warn qo'shilgan edi va unga 1.5em berildi. Ogohlantirish haqli chiqdi: natijada calc(0.09375em * 1rem / 1px) degan ma'nosiz qiymat hosil bo'ldi. Kompilyatsiya to'xtamadi — shuning uchun jiddiy holatlarda @warn emas, @error tanlang.

6. Hammasi birga: «Bahor» Sass versiyasi

scss/_ranglar.scss — yuqoridagi $ranglar map'i. scss/_vositalar.scss:

scss
@use "sass:map";
@use "sass:math";

$ekranlar: (
  "planshet": 40rem,
  "kompyuter": 64rem,
);

// Mobile-first breakpoint (Media queries darsi)
@mixin ekran($nom) {
  @if not map.has-key($ekranlar, $nom) {
    @error "Bunday ekran yo'q: #{$nom}. Bor: #{map.keys($ekranlar)}";
  }

  @media (width >= map.get($ekranlar, $nom)) {
    @content;
  }
}

// px → rem (1rem = 16px)
@function rem($px) {
  @return math.div($px, 16px) * 1rem;
}

scss/_tokenlar.scss:

scss
@use "ranglar";

:root {
  @each $nom, $qiymat in ranglar.$ranglar {
    --rang-#{$nom}: #{$qiymat};
  }
}

scss/_karta.scss:

scss
@use "vositalar" as v;

.taom-karta {
  padding: v.rem(16px);
  border: 2px solid var(--rang-asosiy);
  border-radius: v.rem(8px);

  @include v.ekran("planshet") {
    padding: v.rem(24px);
  }
}

scss/asosiy.scss:

scss
@use "tokenlar";
@use "karta";

Natija — npx sass --no-source-map scss/asosiy.scss:

css
:root {
  --rang-asosiy: #2f6b3a;
  --rang-asosiy-toq: #1a5d1a;
  --rang-urgu: #b4461a;
  --rang-fon: #fffaf0;
  --rang-matn: #1f2a24;
  --rang-ikkinchi: #5b6660;
}

.taom-karta {
  padding: 1rem;
  border: 2px solid var(--rang-asosiy);
  border-radius: 0.5rem;
}
@media (width >= 40rem) {
  .taom-karta {
    padding: 1.5rem;
  }
}
flowchart LR
  R["_ranglar<br/>map"] --> T["_tokenlar<br/>@each"]
  V["_vositalar<br/>mixin, rem()"] --> K["_karta"]
  T --> A["asosiy.scss"]
  K --> A
  A --> C["asosiy.css<br/>:root + karta"]

Nimaga qarang: Sass'ning ishi tugagach, brauzerda oddiy CSS qoladi — CSS o'zgaruvchilari bilan. Kartaning rangi var(--rang-asosiy): qorong'i rejim uni brauzerda almashtira oladi. Sass hisob-kitobni oldi, brauzer esa jonli qismni.

7. Utility class'larni yasash

Sikllarning mashhur ishlatilishi — ko'plab bir vazifali class ("utility") yasash. Tailwind'dan oldin ko'p loyihalar shunday qilgan (CSS metodologiyalari darsidagi utility-first g'oyasi). Namoyish uchun uchta matn rangi (bu class'lar faqat shu misolda, «Bahor»ga ko'chmaydi):

scss
$matn-ranglari: (
  "asosiy": #2f6b3a,
  "urgu": #b4461a,
  "ikkinchi": #5b6660,
);

@each $nom, $rang in $matn-ranglari {
  .matn-#{$nom} {
    color: $rang;
  }
}

Sass chiqargan CSS brauzerda:

html
<style>
  .matn-asosiy {
    color: #2f6b3a;
  }

  .matn-urgu {
    color: #b4461a;
  }

  .matn-ikkinchi {
    color: #5b6660;
  }

  body {
    font-family: system-ui, sans-serif;
    background-color: #fffaf0;
  }
</style>
<h2 class="matn-asosiy">Choyxona «Bahor»</h2>
<p class="matn-urgu">Bugun ko'k choy — 5 000 so'm!</p>
<p class="matn-ikkinchi">Har kuni 7:00 dan 23:00 gacha ochiqmiz.</p>

Nimaga qarang: sarlavha yashil, aksiya qizg'ish, ish vaqti kulrang — uchta class'ni yetti qatorlik sikl yasadi. Map'ga to'rtinchi rang qo'shilsa, to'rtinchi class o'zi paydo bo'ladi. Bugun bu ishni Tailwind avtomatik qiladi (Tailwind 1) — lekin g'oya aynan shu.

8. Bugun Sass qachon kerak?

CSS'ning o'zi ham shu tomonga yuryapti: CSS'ga o'z @function va if() qo'shilmoqda. Baseline ma'lumotiga ko'ra ular hozircha Baseline emas: @function faqat Chrome va Edge 139 dan, if() — 137 dan; Firefox va Safari'da yo'q. @custom-media esa hali hech bir brauzerda yo'q. Ya'ni bugun bularga tayanib bo'lmaydi.

Sass kerak Sass shart emas
Breakpoint mixin, bitta joyda Kichik sayt, bitta-ikkita media query
Map'dan o'nlab qoida yoki token Ranglar, mavzu — CSS o'zgaruvchilari
Hisoblangan shkalalar (clamp, pow) Nesting — brauzer o'zi biladi
Mavjud Sass loyiha, Bootstrap Tailwind loyihasi

Ikkinchi ustundagi hollarda oddiy CSS va keyingi darsdagi PostCSS yetarli. Birinchisida Sass hali o'z o'rnida.

9. Ko'p uchraydigan xatolar

9.1 @extend hamma joyga "yopishdi"

.mashhur { @extend .taom-karta; } dan keyin menyu va aksiya bo'limlaridagi qoidalar ham .mashhur ga tegdi. Tuzatish: mixin yoki placeholder %. Eng yaxshisi — HTML'da ikki class: class="taom-karta mashhur".

9.2 / bilan bo'lish

slash-div ogohlantirishi. Tuzatish: @use "sass:math"; va math.div(a, b).

9.3 Global funksiyalar

map-get(), darken(), lighten() — global-builtin va color-functions ogohlantirishlari. Tuzatish: map.get(), color.adjust() — modul bilan. Ko'p faylda bo'lsa, sass-migrator (Sass/SCSS 1) yordam beradi.

9.4 Mixin CSS'ni shishirdi

Har @include to'liq nusxa. Siqilgan fayl kutilganidan katta chiqdi. Tuzatish: o'zgaradigan qism faqat rang bo'lsa — umumiy class va CSS o'zgaruvchisi, mixin — tuzilma o'zgarganda.

9.5 Blok bor, @content yo'q

Mixin doesn't accept a content block. Tuzatish: mixin ichiga @content; qo'shing yoki @include dan blokni olib tashlang.

10. Mashqlar

Mashqlar kurs/mashqlar/06/ da, sass o'rnatilgan papkada.

1-mashq (oson): rem() funksiyasi

Dizayner o'lchamlarni pikselda berdi: karta ichki bo'sh joyi 20px, burchagi 12px, narx shrifti 18px. rem() funksiyasini yozing va .taom-karta hamda .narx qoidalarida ishlating. Natija rem da chiqsin.

Ishora: @use "sass:math";, bo'lish — math.div, 1rem = 16px.

Yechim
scss
@use "sass:math";

@function rem($px) {
  @return math.div($px, 16px) * 1rem;
}

.taom-karta {
  padding: rem(20px);
  border-radius: rem(12px);
}

.narx {
  font-size: rem(18px);
}

Natija: padding: 1.25rem, border-radius: 0.75rem, font-size: 1.125rem — tekshirdik. 20 ÷ 16 = 1.25, 12 ÷ 16 = 0.75, 18 ÷ 16 = 1.125.

2-mashq (o'rta): kompyuter uchun menyu

$ekranlar map'i va ekran mixin'i bilan (yuqoridagi _vositalar.scss) yozing: header nav ul telefonda ustun (flex-direction: column), planshetdan boshlab qator, kompyuterda esa havolalar orasi 2rem. @include ekran(...) ikki marta ishlatilsin.

Ishora: mobile-first — oddiy qoida telefon uchun, katta ekranlar @include ichida (Mobile-first).

Yechim
scss
@use "vositalar" as v;

header nav ul {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;

  @include v.ekran("planshet") {
    flex-direction: row;
  }

  @include v.ekran("kompyuter") {
    gap: 2rem;
  }
}

Natijada ikkita @media: (width >= 40rem) va (width >= 64rem), har birida header nav ul. @include ikkalasini ham asosiy qoidadan keyin qo'ydi — kaskad tartibi mobile-first'ga mos: katta ekran qoidalari pastda va yutadi.

3-mashq (qiyin): palitradan tokenlar va tekshiruv

_ranglar.scss dagi $ranglar map'idan foydalanib:

  1. :root da hamma --rang-* o'zgaruvchilarini yasang.
  2. rang($nom) funksiyasini yozing: var(--rang-<nom>) qaytarsin, lekin map'da bunday nom bo'lmasa — @error.
  3. .narx { color: rang("urgu"); } va ataylab xato rang("qizil") bilan sinab ko'ring.

Ishora: funksiya ichida ham @if va @error ishlaydi. Qaytariladigan qiymat — interpolyatsiyali matn: var(--rang-#{$nom}).

Yechim
scss
@use "sass:map";
@use "ranglar";

@function rang($nom) {
  @if not map.has-key(ranglar.$ranglar, $nom) {
    @error "Palitrada yo'q: #{$nom}";
  }
  @return var(--rang-#{$nom});
}

:root {
  @each $nom, $qiymat in ranglar.$ranglar {
    --rang-#{$nom}: #{$qiymat};
  }
}

.narx {
  color: rang("urgu");
}

Natija: :root da oltita o'zgaruvchi va .narx { color: var(--rang-urgu); }. rang("qizil") yozilsa, kompilyatsiya Error: "Palitrada yo'q: qizil" bilan to'xtaydi — tekshirdik. Foydasi: oddiy CSS'da var(--rang-qizil) xato bermaydi, jim ishlamaydi. Sass esa yozish paytidayoq to'xtatdi.

4-mashq: Portfolio qadami — clamp() ni Sass hisoblasin

Fluid tipografiya darsida portfolio uchun clamp() formulalarini qo'lda hisoblagan edik: 360 pikselli ekranda eng kichik, 1280 da eng katta qiymat. Endi shu formulani Sass funksiyasiga aylantiring va qo'lda hisoblangan qiymatlarni tekshiring.

  1. Oldingi darsdagi tajriba/ papkasida _fluid.scss yarating: fluid($min, $max) funksiyasi clamp(min, boshlanish + qiyalik, max) qaytarsin. Kichik ekran 360px, katta 1280px — standart argumentlar bilan.
  2. tajriba/fluid-sinov.scss da to'rtta qiymatni hisoblating: body 16→18px, h1 28→40px, h2 22→24px, .loyihalar gap 16→32px.
  3. Kompilyatsiya qiling va natijani portfolio'dagi qiymatlar bilan solishtiring (Dizayn tokenlari darsidan beri ular tokenlar.css da: --step-0, --step-1, --step-2 va --masofa-m-xl).

Ishora — Fluid tipografiya darsidagi formula:

  • qiyalik = (max − min) ÷ (katta ekran − kichik ekran);
  • boshlanish = min − qiyalik × kichik ekran;
  • vw qismi = qiyalik × 100.

Raqamlarni 4 xonagacha yaxlitlang: math.round(son * 10000) ni 10000 ga bo'ling.

Yechim

tajriba/_fluid.scss:

scss
@use "sass:math";

// Kasr sonni 4 xonagacha yaxlitlaydi
@function yaxlit($son) {
  @return math.div(math.round($son * 10000), 10000);
}

// px → rem (1rem = 16px)
@function rem($px) {
  @return math.div($px, 16px) * 1rem;
}

// 360 px ekranda $min, 1280 px da $max, oralig'ida silliq o'sadi
// (Fluid tipografiya darsidagi formula)
@function fluid($min, $max, $tor: 360px, $keng: 1280px) {
  $qiyalik: math.div($max - $min, $keng - $tor);
  $boshlanish: $min - $qiyalik * $tor;
  $vw: yaxlit($qiyalik * 100) * 1vw;

  @return clamp(rem($min), yaxlit(rem($boshlanish)) + $vw, rem($max));
}

tajriba/fluid-sinov.scss:

scss
@use "fluid" as *;

body {
  font-size: fluid(16px, 18px);
}

h1 {
  font-size: fluid(28px, 40px);
}

h2 {
  font-size: fluid(22px, 24px);
}

.loyihalar {
  gap: fluid(16px, 32px);
}

npx sass --no-source-map tajriba/fluid-sinov.scss natijasi:

css
body {
  font-size: clamp(1rem, 0.9511rem + 0.2174vw, 1.125rem);
}

h1 {
  font-size: clamp(1.75rem, 1.4565rem + 1.3043vw, 2.5rem);
}

h2 {
  font-size: clamp(1.375rem, 1.3261rem + 0.2174vw, 1.5rem);
}

.loyihalar {
  gap: clamp(1rem, 0.6087rem + 1.7391vw, 2rem);
}

To'rttalasi ham portfolio'dagi qiymatlar bilan raqamma-raqam bir xil — qo'lda hisob to'g'ri bo'lgan. Endi yangi o'lcham kerak bo'lsa (masalan, h3 uchun 18→20px), kalkulyator emas, fluid(18px, 20px) yozasiz va natijani CSS faylga ko'chirasiz. Portfolio'ning o'zi baribir oddiy CSS'da qoladi: Sass — sizning kalkulyatoringiz, saytning qismi emas.

$qiyalik * $tor da birliklar: $qiyalik birliksiz son (px ÷ px), $tor — px, natija px. Sass birliklarni o'zi kuzatadi — ular mos kelmasa, xato beradi.

11. Real ishda

  • Bootstrap 5 o'z breakpoint'larini map'da ($grid-breakpoints) saqlaydi va media-breakpoint-up() mixin'i bilan ishlatadi; utility class'larining katta qismini map va @each bilan yasaydi. Bugungi dars uning manba kodini o'qishga yetadi.
  • Dizayn tizimlari palitra va o'lchamlarni Sass map'ida saqlab, CSS o'zgaruvchilariga aylantiradi — tokenlarni boshqa formatlardan yasash yo'llarini Dizayn tokenlari darsida ko'rdik.
  • Kod ko'rigida @extend va 3 dan chuqur nesting ko'pincha rad etiladi, / bilan bo'lish va global funksiyalar esa "eskirgan" deb belgilanadi.
  • Intervyuda: "Mixin va @extend farqi?", "Placeholder nima?", "Sass funksiyasi va CSS calc() farqi?" — birinchisi kompilyatsiyada bir marta hisoblaydi, ikkinchisi brauzerda, har o'lchamda.

Xulosa

  • @mixin + @include — qoidalar to'plami; argument, standart qiymat, @content bilan breakpoint mixin.
  • Mixin manba kodni qisqartiradi, CSS'ni emas; rang o'zgarsa — CSS o'zgaruvchisi yaxshiroq.
  • @extend selektorlarni kutilmaganda ko'paytiradi va media query'dan o'tmaydi — o'rniga mixin.
  • @function qiymat qaytaradi; bo'lish — math.div, funksiyalar — sass:math, sass:color, sass:map modullaridan.
  • Map + @each / @for / @if — o'nlab qoida va --rang-* tokenlarni avtomatik yasaydi; @error xatoni erta ushlaydi.

Keyingi dars: PostCSS, Autoprefixer, browserslist va Lightning CSS — yozilgan CSS'ni brauzerlarga moslab avtomatik o'zgartiradigan vositalar.

Manbalar

  • Sass rasmiy hujjati: "@mixin and @include", "@extend", "@function", "Flow Control", "Maps" — sass-lang.com/documentation
  • Sass: "Built-In Modules" (sass:math, sass:color, sass:map) — sass-lang.com/documentation/modules
  • Sass: "Breaking Change: Slash as Division" — sass-lang.com/d/slash-div
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Sass/SCSS 2: mixin, funksiya, map va boshqaruv — IlmHamroh