Kurs HTML i CSS · Moduł 7: SASS

Mapy i listy w Sass

4 min czytania
W tej lekcji5

Wyobraź sobie że Twoja świątynia potrzebuje pięciu rozmiarów tekstu, czterech kolorów i czterech progów responsywności. Z samymi zmiennymi skończysz z tuzinem luźnych deklaracji w rodzaju $size-1 i $color-primary, a każdą klasę pomocniczą napiszesz ręcznie. Sass oferuje dwie struktury danych, które porządkują takie wartości: listy i mapy. Wyobraź je sobie jak katalogi skarbów w egipskiej świątyni: listy to uporządkowane spisy, a mapy to katalogi z opisami.

Listy w Sass

Lista to kolekcja wartości oddzielonych spacjami lub przecinkami, jak papirus z wykazem imion faraonów. Poniżej zobaczysz oba rodzaje separatorów i pierwszą pętlę, która przechodzi po liście dyrektywą @each:

1// Lista oddzielona spacjami
2$spacing: 4px 8px 16px;
3
4// Lista oddzielona przecinkami (nazwy czcionek)
5$font-stack: Helvetica, Arial, sans-serif;
6
7// Lista oddzielona przecinkami
8$sizes: 12px, 14px, 16px, 18px, 24px;
9
10// Iteracja po liście z @each
11@each $size in $sizes {
12  .text-#{$size} {
13    font-size: $size;
14  }
15}

Pętla @each bierze po kolei każdy element listy $sizes i generuje dla niego klasę, więc po kompilacji dostaniesz reguły od .text-12px do .text-24px. Zapis #{$size} to interpolacja, która wstawia wartość zmiennej do nazwy selektora. Lista $spacing z odstępami rozdzielonymi spacjami działa dokładnie tak samo, różni się tylko separator.

Do pracy z listami służą wbudowane funkcje:

  • length($lista) - zwraca liczbę elementów
  • nth($lista, $index) - zwraca element o podanym indeksie (indeks zaczyna się od 1)
  • append($lista, $wartość) - dodaje element na koniec
  • join($lista1, $lista2) - łączy dwie listy

Pobierzmy teraz drugi element listy kolorów funkcją nth():

1$colors: red, blue, green;
2
3.element {
4  color: nth($colors, 2); // blue
5}

Indeks 2 wskazuje blue, bo w Sass liczymy od jedynki, a nie od zera jak w JavaScripcie. Pamiętaj też, że listy w Sass są niezmienne: append() i join() nie modyfikują oryginału, tylko zwracają nową listę, którą trzeba zapisać do zmiennej.

Mapy w Sass

Mapa to zbiór par klucz-wartość, niczym tajemny katalog egipskich artefaktów, w którym każdy przedmiot ma swoją etykietę. Definiujemy ją w nawiasach okrągłych, a pary oddzielamy przecinkami:

1$breakpoints: (
2  "mobile": 320px,
3  "tablet": 768px,
4  "desktop": 1024px,
5  "wide": 1440px
6);
7
8$colors: (
9  "primary": #2C3E50,
10  "secondary": #D4AF37,
11  "accent": #E74C3C,
12  "background": #F5F0E1
13);

Klucze w cudzysłowie to nazwy, a po dwukropku stoją wartości. Sama definicja, tak jak zwykła zmienna, nie generuje żadnego CSS.

Aby pobrać wartość z mapy, używamy funkcji map-get(), która przyjmuje mapę i klucz:

1.header {
2  background-color: map-get($colors, "primary");
3  color: map-get($colors, "secondary");
4}

Nagłówek dostanie tło #2C3E50 i złoty tekst #D4AF37. Klucz możesz zapisać w cudzysłowie pojedynczym lub podwójnym, bo Sass traktuje oba tak samo. Uważaj za to na literówki: dla nieistniejącego klucza map-get() zwraca null, a deklaracja z taką wartością po prostu znika z CSS, bez żadnego błędu.

W nowych projektach spotkasz też zapis modułowy: po dodaniu na początku pliku @use "sass:map" piszesz map.get($colors, "primary"). Działa identycznie, a globalne funkcje w rodzaju map-get() są w nowszych wersjach Dart Sass oznaczone jako przestarzałe. Polecam Ci zapis modułowy choć starszy wciąż jest wszędzie w dokumentacji i starszym kodzie.

Iteracja po mapach z @each

Prawdziwa siła map ujawnia się w pętli. Dyrektywa @each może pobierać jednocześnie klucz i wartość, więc możemy automatycznie wygenerować klasy na podstawie mapy:

1@each $name, $color in $colors {
2  .text-#{$name} {
3    color: $color;
4  }
5  .bg-#{$name} {
6    background-color: $color;
7  }
8}

Po kompilacji otrzymamy klasy .text-primary, .text-secondary, .bg-primary itd. Dodanie nowego koloru do mapy wystarczy, by pętla sama dopisała dla niego obie klasy.

Mapy dla breakpointów

Jednym z najczęstszych zastosowań map jest przechowywanie breakpointów i używanie ich w media queries. Poniższy mixin pobiera szerokość z mapy, a dyrektywa @content wstawia w media query blok przekazany przy @include:

1$breakpoints: (
2  "sm": 576px,
3  "md": 768px,
4  "lg": 1024px,
5  "xl": 1200px
6);
7
8@mixin respond-to($breakpoint) {
9  $value: map-get($breakpoints, $breakpoint);
10  @media (min-width: $value) {
11    @content;
12  }
13}
14
15.container {
16  width: 100%;
17
18  @include respond-to("md") {
19    width: 750px;
20  }
21
22  @include respond-to("lg") {
23    width: 970px;
24  }
25}

Kompilator zamieni każde wywołanie na zwykłe media query, na przykład @media (min-width: 768px) z szerokością 750px dla .container. Progi zmieniasz odtąd w jednym miejscu, a nazwy w rodzaju "md" czyta się łatwiej niż surowe piksele.

Przydatne funkcje dla map

  • map-get($mapa, $klucz) - pobiera wartość
  • map-has-key($mapa, $klucz) - sprawdza, czy klucz istnieje
  • map-keys($mapa) - zwraca listę kluczy
  • map-values($mapa) - zwraca listę wartości
  • map-merge($mapa1, $mapa2) - łączy dwie mapy

Mapy i listy to narzędzia organizacji kodu na wyższym poziomie. Pozwalają przechowywać konfigurację w jednym miejscu i generować style automatycznie, jak sprawny system zarządzania zasobami w starożytnej świątyni. Spróbuj dodać do mapy $colors turkus i skompilować arkusz, a pętla sama utworzy klasy .text-turquoise i .bg-turquoise.

Pamiętaj: lista to spis skarbów, a mapa to katalog z etykietami, z którego map-get() wydaje dokładnie ten przedmiot, o który poprosisz.

Kod do tej lekcji: index.html
1<!DOCTYPE html>
2<html lang="pl">
3<head><title>Formularze HTML</title></head>
4<body style="background:#d4a574;font-family:serif;padding:20px;color:#3d2914">
5<h1>Formularze HTML</h1>
6<form><label>Imię pisarza: <input type="text"></label></form>
7</body>
8</html>

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Jak pobrać wartość z mapy SASS o nazwie $colors dla klucza 'primary'?

Przydatne artykuły