Moduł 3 - Zajęcia 4 - Flexbox

1.1 Flex

Flexible Box Layout (Flexbox) — to moduł CSS, który definiuje zestaw właściwości do umieszczania, wyrównywania i dystrybucji przestrzeni między elementami w kontenerze, nawet jeśli ich rozmiar jest nieznany lub dynamiczny. Główną ideą jest podzielenie elementów na kontener blokowy (flex-container) i jego dzieci (flex-elements).

Elastyczny kontener może:

  • zmieniać szerokość i wysokość swoich dzieci;
  • zmienić kierunek swoich dzieci (wyrównanie w kolumnie lub wierszu);
  • zmieniać kolejność wyświetlania elementów i odległość między nimi;
  • rozszerzać elementy, aby optymalnie wypełnić dostępną przestrzeń;
  • kompresować elementy, aby zapobiec ich przepełnieniu.

W elastycznym kontenerze większość zasad rozmieszczania elementów zgodnie z ich typem i przepływem dokumentu zostaje anulowana. Elementy tracą swój "typ", nie są już elementami liniowymi lub blokowymi, stają się elementami elastycznymi. Elementy blokowe nie są już umieszczone pionowo jeden pod drugim. Marginesy zewnętrzne elementów na krawędzi elementu nadrzędnego nie wypadają. Pionowe marginesy zewnętrzne nie zwijają się. Działają automatyczne odstępy pionowe.

1.2 Osie prowadzące flex kontenera

Normalna kolejność elementów jest określona przez przepływ dokumentu i ich typ (blokowy lub liniowy). Jednak jak już wiesz, w przypadku Flexbox tak nie jest. W modelu Flexbox kierunek elementów jest określany przez osie kontenera, wzdłuż których ustawiane są elementy.

Spójrzmy na główne osie kontenera. Jest to absolutnie konieczne, aby zrozumieć, na co będą miały wpływ właściwości, które przeanalizujemy w następnej sekcji.

Main axis

main axis — to główna oś kontenera elastycznego, wzdłuż której umieszczane są elementy. Kierunek głównej osi jest kontrolowany przez właściwość flex-direction i może być poziomy (sample A) oraz pionowy (sample B).

Cross axis

cross axis — oś poprzeczna, która jest zawsze prostopadła do osi głównej (main axis). Jej kierunek nie jest wyraźnie określony, ponieważ zawsze zależy od main axis:

  • jeśli main axis jest pozioma, cross axis jest pionowa (sample A)
  • jeśli main axis jest pionowa, cross axis jest pozioma (sample B)

Model Flexbox ma punkty "start" i "end", które definiują kolejność elementów wewnątrz kontenera elastycznego.

  • Osie (main axis, cross axis) definiują linie, wzdłuż których umieszczane są elementy.
  • Punkty "start" i "end" są dosłownie punktami początkowymi i końcowymi na osi głównej lub poprzecznej. Określają one, gdzie będzie znajdował się pierwszy i ostatni element na osi.

Spójrzmy na początek i koniec main axis.

main-start i main-end — elementy w kontenerze zawsze są umieszczane od main-start (początek głównej osi) do main-end (koniec głównej osi).

cross-start i cross-end są początkiem i końcem osi poprzecznej cross axis, wzdłuż której znajdują się rzędy elementów.

Nie oczekuj, że start będzie zawsze w lewym górnym rogu, a end w prawym dolnym rogu. Możesz skonfigurować dowolną kolejność elementów — od lewej do prawej lub od prawej do lewej, od góry do dołu lub od dołu do góry. Punkty start i end są bezpośrednio zależne od kierunku osi.

1.3 Właściwości kontenera

Kontener elastyczny

Kontener elastyczny (zwany dalej kontenerem) — to element nadrzędny grupy elementów, który umożliwia zmianę kolejności elementów wewnątrz. To właściwości kontenera kontrolują:

  • kierunek osi;
  • wielowierszowość;
  • pozycjonowanie elementów w rzędzie.

Właściwość display tworzy blokowy lub liniowo-blokowy kontener elastyczny.

            display: flex | inline-flex
          

W zależności od określonej wartości właściwość ustawia elastyczny kontekst dla wszystkich dzieci (nie potomków) kontenera, przekształcając je w elementy elastyczne.

            <ul class="menu">
              <li class="item"><a href="" class="link">Main page</a></li>
              <li class="item"><a href="" class="link">Blog</a></li>
              <li class="item"><a href="" class="link">Podcasts</a></li>
              <li class="item"><a href="" class="link">Contact</a></li>
            </ul>
          

Utwórzmy menu poziome, konwertując ul.menu na kontener elastyczny. Następnie jego dzieci, elementy li.item, zostaną ułożone wzdłuż głównej osi, która domyślnie przebiega od lewej do prawej.

            .menu {
              display: flex;
            }
          

W poprzednim kroku do elementów menu została dodana właściwość display: flex;. Teraz są one ułożone poziomo w jednej linii, a także przyciśnięte do siebie.

Aby ustawić odstęp między elementami elastycznymi, użyj właściwości gap kontenera elastycznego. W naszym projekcie będzie to 8px. W przypadku kolekcji elementów właściwość gap zastępuje zewnętrzne odstępy, więc nie musisz ustawiać je dla każdego elementu osobno.

Dodajmy właściwość gap do kontenera, czyli do reguły z selektorem .menu. Teraz między elementami będzie odstęp 8px.

            .menu {
              display: flex;
              gap: 8px;
            }
          

1.4 flex-direction

Właściwość: flex-direction - flexbox to system do układania elementów w jednym określonym kierunku - poziomym lub pionowym. Właściwość flex-direction ustala kierunek głównej osi, definiując kierunek elementów w kontenerze.

  • row - oś zaczyna się po lewej stronie i kończy po prawej stronie. To jest wartość domyślna.
  • row-reverse - oś zaczyna się po prawej stronie i kończy po lewej stronie.
  • column - oś zaczyna się u góry i kończy u dołu.
  • column-reverse - oś zaczyna się u dołu i kończy u góry.

Tak więc ta właściwość zamienia main-start i main-end głównej osi. Elementy elastyczne będą zawsze umieszczane wzdłuż głównej osi od początku (main-start) do końca (main-end).

  • row
  • 1
  • 2
  • 3
  • 4
  • row-reverse
  • 1
  • 2
  • 3
  • 4
  • column
  • 1
  • 2
  • 3
  • 4
  • column-reverse
  • 1
  • 2
  • 3
  • 4

1.5 justify-content

Właściwość: justify-content - Steruje pozycjonowaniem elementów na głównej osi, od main-start do main-end. Prawdopodobnie najczęstszym zastosowaniem jest centrowanie elementów w pionie w wierszu, zwłaszcza jeśli elementy mają różne wysokości.

  • flex-start - elementy są dociskane do początku osi. To jest ustawienie domyślne
  • flex-end - elementy są dociskane do końca osi.
  • center - elementy są wyśrodkowane na osi.
  • space-between - elementy są rozłożone równomiernie, pierwszy element przy początku osi, ostatni przy końcu osi.
  • space-around - elementy są rozmieszczone równomiernie, ale lewy i prawy element pozostają w tyle za granicami kontenera o połowę odstępu między innymi elementami
  • space-evenly - elementy są rozmieszczone w taki sposób, aby odległość między elementami i od elementów krawędziowych do granic kontenera była taka sama.
  • flex-start
  • 1
  • 2
  • 3
  • 4
  • flex-end
  • 1
  • 2
  • 3
  • 4
  • center
  • 1
  • 2
  • 3
  • 4
  • space-between
  • 1
  • 2
  • 3
  • 4
  • space-around
  • 1
  • 2
  • 3
  • 4
  • space-evenly
  • 1
  • 2
  • 3
  • 4

1.6 align-items

Właściwość align-items kontroluje rozmieszczenie elementów wzdłuż cross axis. Jest ona analogiczna do justify-content, ale dla innej osi.

  • flex-start - elementy są dociskane do początku osi.
  • flex-end - elementy są dociskane do końca osi.
  • center - elementy są wyśrodkowane na osi.
  • stretch - elementy rozciągają się, aby wypełnić kontener (to jest ustawienie domyślne).
  • baseline - elementy są wyrównane do linii bazowej.
  • flex-start
  • 1
  • 2
  • 3
  • 4
  • flex-start
  • 1
  • 2
  • 3
  • 4
  • flex-start
  • 1
  • 2
  • 3
  • 4
  • flex-start
  • 1
  • 2
  • 3
  • 4
  • flex-start
  • 1
  • 2
  • 3
  • 4
  • flex-end
  • 1
  • 2
  • 3
  • 4
  • flex-end
  • 1
  • 2
  • 3
  • 4
  • flex-end
  • 1
  • 2
  • 3
  • 4
  • flex-end
  • 1
  • 2
  • 3
  • 4
  • flex-end
  • 1
  • 2
  • 3
  • 4
  • center
  • 1
  • 2
  • 3
  • 4
  • center
  • 1
  • 2
  • 3
  • 4
  • center
  • 1
  • 2
  • 3
  • 4
  • center
  • 1
  • 2
  • 3
  • 4
  • center
  • 1
  • 2
  • 3
  • 4
  • stretch
  • 1
  • 2
  • 3
  • 4
  • stretch
  • 1
  • 2
  • 3
  • 4
  • stretch
  • 1
  • 2
  • 3
  • 4
  • stretch
  • 1
  • 2
  • 3
  • 4
  • stretch
  • 1
  • 2
  • 3
  • 4
  • baseline
  • 1
  • 2
  • 3
  • 4
  • baseline
  • 1
  • 2
  • 3
  • 4
  • baseline
  • 1
  • 2
  • 3
  • 4
  • baseline
  • 1
  • 2
  • 3
  • 4
  • baseline
  • 1
  • 2
  • 3
  • 4

1.7 flex-wrap

Domyślnie display: flex tworzy jednowierszowy kontener, z elementami umieszczonymi w jednej linii i skompresowanymi w razie potrzeby.

Właściwość flex-wrap pozwala na przekształcenie kontenera jednowierszowego w kontener wielowierszowy. Elementy będą dodawane do linii, dopóki będzie w niej miejsce, po czym automatycznie zostanie utworzona kolejna linia.

Właściwość flex-wrap ma następujące wartości:

            flex-wrap: nowrap | wrap | wrap-reverse
          
  • nowrap — wszystkie elementy będą w tej samej linii. Jest to wartość domyślna.
  • wrap — pozwala elementom przeskakiwać do innych wierszy, które domyślnie są ułożone od góry do dołu (wzdłuż cross axis).
  • wrap-reverse — pozwala elementom przeskakiwać do innych wierszy, które domyślnie są ułożone od dołu do góry (wzdłuż cross axis).

1.8 Siatka elementów

Wielowierszowy kontener elastyczny umożliwia tworzenie "siatki" elementów, takich jak karty produktów w sklepie internetowym, podglądy artykułów na blogu, galeria obrazów itp.

Pierwszą rzeczą do zrobienia jest przekonwertowanie ul.card-set na kontener elastyczny i uczynienie go wielorzędowym.

            .card-set {
              display: flex;
              flex-wrap: wrap;
            }
          

Następnie użyjemy właściwości gap, aby ustawić odstęp między kolumnami i wierszami siatki. Powiedzmy, że w naszym wyimaginowanym layoucie jest to 10px.

            .card-set {
              display: flex;
              flex-wrap: wrap;
              gap: 10px;
            }
          

Właściwość gap łączy w sobie wartości właściwości row-gap i column-gap, które umożliwiają oddzielne ustawianie odstępów między wierszami i kolumnami siatki. Używaj gap, gdy odstępy są takie same, w przeciwnym razie możesz użyć właściwości row-gap i column-gap.

Ostatnim krokiem jest ustawienie rozmiaru elementów elastycznych li.item. Szerokość jest określana jako procent całkowitej szerokości elementu nadrzędnego (100%) przy użyciu następującego wzoru:

            (100% - liczba_odstępów_w_wierszu * wartość_jednego_odstępu) / liczba_elementów_w_wierszu
          

Liczba odstępów między elementami w wierszu jest zawsze o jeden mniejsza niż liczba elementów. W naszej siatce na wiersz przypadają trzy elementy, więc na każdy wiersz przypadają dwa odstępy 10px.

            .item {
              width: calc((100% - 20px) / 3);
            }
          

Funkcja CSS calc() przyjmuje jako parametr wyrażenie matematyczne, którego wynik może być użyty jako wartość właściwości CSS. Wyrażenie może zawierać operatory +, -, *, / przy użyciu standardowych reguł pierwszeństwa.

Czemuż by nie użyć stałych wartości? Procentowe szerokości elementów są skalowalnym rozwiązaniem, ponieważ nie trzeba ponownie obliczać rozmiarów elementów, gdy zmieniasz szerokość kontenera lub odstępy między nimi.

1.9 Właściwość align-content

Kontroluje wyrównanie wszystkich wierszy kontenera wielowierszowego wzdłuż cross axis, jeśli jest na to miejsce. Podobnie jak align-items wyrównuje elementy w każdym rzędzie, ale nie działa, gdy jest tylko jeden wiersz elementów lub brak miejsca w pionie w kontenerze (brak jawnie określonej wysokości większej niż treść).

            align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch
          
  • stretch — wiersze są rozciągane równomiernie, aby zająć całą przestrzeń. Wartość domyślna.
  • flex-start — wiersze są przyciśnięte do początku cross axis.
  • flex-end — wiersze są przyciśnięte do końca cross axis.
  • center — ciągi są wyśrodkowane na cross axis.

Wartości space-between, space-around i space-evenly działają podobnie do właściwości justify-content, tylko dla wierszy i są rzadko używane.

2.1 Elementy elastyczne

Elementy elastyczne są dziećmi kontenera elastycznego, czyli elementami pierwszego poziomu zagnieżdżenia.

W modelu Flexbox elementy elastyczne (dalej elementy):

  • nie przestrzegają już standardowego przepływu dokumentów;
  • tracą swój typ (blok, linia itp.)
  • przestrzegają zasad pozycjonowanego modelu Flexbox.

2.2 Właściwość flex-basis

Właściwość flex-basis definiuje początkowy rozmiar elementu elastycznego w kontenerze elastycznym.

Początkowy rozmiar jest rozmiarem przed zastosowaniem właściwości flex-grow i flex-shrink, które również wpłyną na rozmiar elementów względem siebie. Przyjrzymy się im później.

Wartość właściwości flex-basis może być dowolną prawidłową wartością: px lub %. Dla elementów elastycznych właściwość ta ma taką samą funkcję jak właściwość width. Ale w praktyce używana jest albo width, albo flex-basis, która definiuje początkowy rozmiar elementu w kontenerze.

            flex-basis: auto | wartość
          
  • Jeśli zastosowano właściwości flex-basis i width, właściwość width jest ignorowana.
  • Właściwość flex-basis może definiować wysokość, ale nie szerokość elementu. Dzieje się tak, gdy kierunek głównej osi jest pionowy.
  • Właściwości min-width i max-width działają jako ograniczniki rozmiaru dla elementu, nawet jeśli posiada on właściwość flex-basis.
  • Właściwość flex-basis nie jest ostatecznym rozmiarem elementu, ale rozmiarem przed alokacją wolnej przestrzeni, która jest kontrolowana przez właściwości flex-grow i flex-shrink.

2.3 Właściwość flex-grow

Właściwość flex-grow definiuje zdolność elementu do zajmowania większej przestrzeni (wzrostu) niż jego pierwotny rozmiar. Wartość jest definiowana jako proporcja (udział) wolnej przestrzeni w kontenerze.

            flex-grow: udział
          

Domyślnie wszystkie elementy są ustawione na 0. Oznacza to, że domyślnie elementy nie próbują zajmować dodatkowego wolnego miejsca, nawet jeśli jest ono dostępne. Wartości ujemne nie mogą być ustawione.

Ważne jest nie to, jaka jest wartość flex-grow elementu sama w sobie, ale jaka jest w odniesieniu do innych elementów.

Jeśli ustawimy każdy element na flex-grow: 1, a następnie zmienimy flex-grow dla trzeciego elementu, zobaczymy zmiany: zajmie on 2, 3 i 6 razy więcej miejsca w wierszu niż inne elementy.

Oznacza to, że właściwość flex-grow kontroluje proporcje elementów względem siebie. Jeśli ustawimy każdy element na flex-grow: 4, a trzeci element na flex-grow: 12, otrzymamy taki sam wynik, jak w przypadku wartości odpowiednio 1 i 3.

Elastyczna treść

Typowym przypadkiem użycia tej właściwości jest pasek boczny o stałej szerokości i elastyczna treść, która zajmuje całą pozostałą przestrzeń w wierszu.

            <div class="container">
              <aside class="sidebar">Sidebar</aside>
              <main class="content">Main content</main>
            </div>
          

Jeśli ustawisz div.container jako kontener elastyczny, pasek boczny będzie mieć stałą szerokość w wierszu, a szerokość main.content będzie określona przez szerokość jego zawartości.

Wszystko, co musisz zrobić, to ustawić właściwość main.content na flex-grow: 1, aby kontener zajął całą dostępną przestrzeń w wierszu.

Main content

Przyklejona stopka strony

Innym częstym przypadkiem użycia właściwości flex-grow jest sytuacja, w której musisz przycisnąć obramowanie strony do dołu strony, niezależnie od ilości jej głównej zawartości.

            <header>Page header</header>
            <main>Main content</main>
            <footer>Page footer</footer>
          

Jeśli zawartość main jest wystarczająca, strona może wyglądać następująco: nagłówek u góry, następnie zawartość główna i stopka u dołu strony.

Problem polega na tym, że jeśli nie ma wystarczającej ilości treści głównej, aby rozciągnąć ją w pionie, strona będzie wyglądać tak (patrz poniższy schemat). Trzy elementy w linii są umieszczone jeden pod drugim, w zależności od ustalonej wysokości lub ilości treści, którą zawierają.

Nawet jeśli ustawimy nagłówek i stopkę na stałą wysokość, nie możemy z góry wiedzieć, jaka będzie wysokość zawartości strony. Dlatego możemy stwierdzić, że wysokość main powinna być zawsze określana przez jej zawartość i nie powinna być ustawiana jawnie.

Z pomocą Flexbox możesz upewnić się, że stopka jest zawsze dociśnięta do dołu strony, niezależnie od ilości zawartości main.

Do implementacji potrzebujemy dodatkowego elementu — wrappera.

            <div class="page-container">
              <header>Page header</header>
              <main>Main content</main>
              <footer>Page footer</footer>
            </div>
          

Najpierw ustawimy jego minimalną wysokość na 100% wysokości zakładki przeglądarki na ekranie użytkownika, używając jednostek vh (viewport height — to procent wysokości obszaru wyświetlania; 5vh = 5% wysokości).

            .page-container {
              min-height: 100vh;
            }
          

Następnie przekonwertujemy go na kontener elastyczny i zmienimy kierunek głównej osi na pionowy, tj. od góry do dołu. Wymusi to ułożenie elementów elastycznych w kolumnie.

            .page-container {
              min-height: 100vh;
              display: flex;
              flex-direction: column;
            }
          

Pozostaje tylko ustawić main właściwość flex-grow, aby umożliwić jej zajęcie całej wolnej przestrzeni na osi głównej, przesuwając stopkę na jej koniec, tj. w dół.

            main {
              flex-grow: 1;
            }
          

Teraz, niezależnie od tego, ile treści znajduje się w main, zawsze zajmuje ona całe wolne miejsce na osi głównej po stopce i nagłówku.

Page header
Main content

2.4 Właściwość flex-shrink

W przeciwieństwie do właściwości flex-grow, flex-shrink definiuje zdolność elementu do zajmowania mniej miejsca (kompresowania) niż jego pierwotny rozmiar, tj. wpływa na ostateczny rozmiar elementu.

            flex-shrink: wartość;
          

Wartość jest określana jako proporcja (ułamek, współczynnik).

  • Domyślnie, wszystkie elementy są ustawione na 1, tzn. elementy będą się zmniejszać zgodnie z potrzebami.
  • Wartość 0 zapobiegnie kompresji elementu. Wartości ujemne nie mogą być ustawione.

W praktyce flex-shrink jest zwykle używany do zapobiegania kompresowaniu elementu. Rozważmy standardowy problem. Mamy kontener z dwoma elementami: elementem dekoracyjnym, takim jak ikona z obrazkiem w tle i tekstem.

            <div class="card">
              <span class="icon"></span>
              <p>
                Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet earum odio
                harum! Nulla aliquid quasi facere atque, corrupti voluptatum cupiditate
                placeat delectus, velit alias dicta praesentium iste amet eos vero.
              </p>
            </div>
            .card {
              display: flex;
              gap: 10px;
              width: 300px;
              border: 1px solid black;
              padding: 10px;
            }

            .icon {
              width: 40px;
              height: 40px;
            }
          

Ikona ma określoną wysokość i szerokość w CSS

Ale spójrzmy na wynik w przeglądarce — element ikony jest skompresowany przez tekst po prawej stronie, ponieważ jest domyślnie ustawiony na flex-shrink: 1 i element z tekstem zajmuje więcej miejsca w wierszu, kompresując ikonę.

Aby element ikony zajmował wymagane 40px szerokości, można zablokować jego kompresję, ustawiając flex-shrink: 0. W ten sposób kontener przydzieli dokładnie 40px dla ikony, a reszta miejsca w wierszu zostanie zajęta przez akapit tekstowy.

            .icon {
              flex-shrink: 0;
              width: 40px;
              height: 40px;
            }
          

Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet earum odio harum! Nulla aliquid quasi facere atque, corrupti voluptatum cupiditate placeat delectus, velit alias dicta praesentium iste amet eos vero.

Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet earum odio harum! Nulla aliquid quasi facere atque, corrupti voluptatum cupiditate placeat delectus, velit alias dicta praesentium iste amet eos vero.

2.5 Właściwość align-self

Właściwość align-self pozwala elementowi na zmianę jego pozycji na cross axis poprzez nadpisanie wartości właściwości align-items z kontenera.

            align-self: auto | flex-start | flex-end | center | baseline | stretch
          

Dla main axis nie ma odpowiednika, a element może przesuwać się tylko na osi poprzecznej.

Wróćmy do przykładu karty graficznej z treścią tekstową.

Aby rozwiązać problem rozciągnięcia obrazka w pionie, użyliśmy właściwości kontenera align-items. Właściwość align-self pozwala na bardziej precyzyjne rozwiązanie tego problemu poprzez nadpisanie wartości align-items tylko dla obrazka.

            .card img {
             align-self: flex-start;
            }
          
  • auto
  • 1
  • 2
  • 3
  • 4
  • flex-start
  • 1
  • 2
  • 3
  • 4
  • flex-end
  • 1
  • 2
  • 3
  • 4
  • center
  • 1
  • 2
  • 3
  • 4
  • baseline
  • 1
  • 2
  • 3
  • 4
  • stretch
  • 1
  • 2
  • 3
  • 4

2.6 Właściwość order

Domyślnie elementy są umieszczane w kolejności, w jakiej zostały określone w pliku HTML. Korzystając z właściwości order, możesz wizualnie zmienić kolejność elementów wzdłuż main axis. W tym przypadku w kodzie HTML nic się nie zmieni. Domyślnie wszystkie elementy mają wartość 0.

            order: położenie;
          

Właściwość ta jest rzadko używana, ponieważ narusza połączenie między wizualną kolejnością elementów a tym, jak są one widziane przez przeglądarkę i technologie wspomagające, jednak wiedzieć o niej warto, bo możesz jej potrzebować w przyszłości.

  1. 1 - order:1
  2. 2 - order:0
  3. 3 - order:2
  4. 4 - no order
  5. 5 - order:3

3.1 Pseudoklasy strukturalne

Elementy sąsiadujące

Pseudoklasy strukturalne są sposobem na wybranie określonych elementów z kolekcji elementów podrzędnych (sąsiadów) bez przypisywania dodatkowych klas. Elementy podrzędne (sąsiedzi) to elementy posiadające wspólnego rodzica.

            <ul class="list">
              <li class="list-item">
                <a class="list-link">Link 1</a>
              </li>
              <li class="list-item">
                <a class="list-link">Link 2</a>
              </li>
              <li class="list-item">
                <a class="list-link">Link 3</a>
              </li>
            </ul>
          

W powyższym przykładzie, elementy li.list-item są sąsiadami i będzie można zastosować do nich pseudoklasy strukturalne.

W tym samym czasie, linki a.list-link nie są sąsiadami, nie mają wspólnego rodzica, więc nie możesz użyć pseudoklas do wybrania konkretnego linku lub grupy linków.

3.2 Pseudoklasy :first-child i :last-child

Pseudoklasy :first-child i :last-child pozwalają na utworzenie selektora, który odnosi się tylko do pierwszego lub ostatniego elementu w kolekcji sąsiadujących elementów.

            <ul class="list">
              <li class="list-item">HTML</li>
              <li class="list-item">CSS</li>
              <li class="list-item">JavaScript</li>
              <li class="list-item">React</li>
            </ul>

            .list-item {
              color: blue;
            }

            .list-item:first-child {
              color: red;
            }

            .list-item:last-child {
              color: green;
            }
          

Wyobraź sobie, że zgodnie z layoutem pomiędzy elementami listy powinien znajdować się margines zewnętrzny (pomarańczowy na poniższym schemacie). Każdy element listy musi mieć dolny lub górny margin.

Jednak w tym przypadku nie jest potrzebny górny margines zewnętrzny dla pierwszego elementu ani dolny margines zewnętrzny dla ostatniego elementu w kolekcji.

Skrajne geometrie, czy to pionowe, czy poziome, muszą zostać usunięte, ponieważ takie marginesy nie mogą w oczywisty sposób przedłużać lub rozszerzać elementu nadrzędnego.

            .list-item {
              margin-bottom: 12px;
            }

            .list-item:last-child {
              margin-bottom: 0;
            }
          
  • HTML
  • CSS
  • JavaScript
  • React - źle - dolny margines
  • HTML
  • CSS
  • JavaScript
  • React - dobrze

3.3 Pseudoklasa :not()

Pseudoklasa :not() pozwala wybrać wszystkie elementy, które nie spełniają kryterium.

Kryterium jest podawane w formie prostego selektora zapisanego w nawiasach. Prosty selektor jest selektorem uniwersalnym, selektorem typu, identyfikatorem, atrybutem, klasą lub pseudoklasą.

            :not(selector)
          

Ta pseudoklasa może być użyta do innego rozwiązania problemu czyszczenia marginesu skrajnego pierwszego lub ostatniego elementu.

Zamiast ustawiać odstęp dla wszystkich elementów w jednej regule, a następnie pamiętać o zresetowaniu go do zera dla określonego elementu w innej regule, ustawiamy odstęp dla wszystkich elementów z wyjątkiem jednego w jednej regule.

            .list-item:not(:last-child) {
              margin-bottom: 20px;
            }
          

Czyta się to następująco: zastosuj style do wszystkich elementów z klasą list-item, które nie są ostatnim elementem w kolekcji sąsiadów. Czyli selektor ten stosuje się do wszystkich elementów w kolekcji z wyjątkiem ostatniego.

  • HTML
  • CSS
  • JavaScript
  • React - źle - dolny margines
  • HTML
  • CSS
  • JavaScript
  • React - dobrze

3.4 Pseudoklasa :nth-child(an + b)

Pseudoklasa :nth-child(an + b) wybiera elementy w kolekcji sąsiadów według liczby określonej w nawiasach za pomocą pętli an + b, która pozwala ustawić regułę dla kolejności elementów.

  • a — okres pętli. Dowolna liczba.
  • n — licznik pętli. Zaczyna się od zera i jest zwiększany o jeden przy każdej iteracji.
  • b — przesunięcie. Dowolna liczba.

Na przykład, jeśli a = 2, oraz b = 1, to an + b = 2n +1. Ten wzór wybierze wszystkie nieparzyste elementy.

            # Przy n = 0
            2 * 0 + 1 = 1

            # Przy n = 1
            2 * 1 + 1 = 3

            # Przy n = 2
            2 * 2 + 1 = 5

            # I tak dalej dla n = 3, n = 4 ...
          

W praktyce ta pseudoklasa jest używana do wybierania wszystkich parzystych lub nieparzystych elementów kolekcji. Na przykład, aby wiersze tabeli miały różne kolory co drugi wiersz.

Utwórzmy znacznik dla listy dziesięciu elementów i zmieńmy ich kolor tła.

            <ul class="list">
              <li class="list-item">1</li>
              <li class="list-item">2</li>
              <li class="list-item">3</li>
              <li class="list-item">4</li>
              <li class="list-item">5</li>
              <li class="list-item">6</li>
              <li class="list-item">7</li>
              <li class="list-item">8</li>
              <li class="list-item">9</li>
              <li class="list-item">10</li>
            </ul>
          

Aby wybrać wszystkie parzyste elementy, możesz użyć wzoru 2n lub jego aliasu - słowa kluczowego even.

            .list-item:nth-child(2n) {
              background-color: orange;
            }

            /* Analogicznie, używając aliasu */
            .list-item:nth-child(even) {
              background-color: orange;
            }
          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Aby wybrać nieparzyste elementy, możesz użyć wzoru 2n + 1 lub jego aliasu — wartości odd, zarezerwowanego słowa.

            .list-item:nth-child(2n + 1) {
             background-color: orange;
            }

            /* Analogicznie, używając aliasu */
            .list-item:nth-child(odd) {
             background-color: orange;
            }
          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10