HTML I CSS · INF.03 · MODUŁ 07
CSS — selektory, kaskada i specyficzność
CSS to nie lista przypadkowych właściwości. To system reguł — poznasz kolejność, która decyduje o wyglądzie.
Wprowadzenie
CSS opisuje wygląd dokumentu HTML. Nie jest listą przypadkowych właściwości, ale zbiorem reguł: selektor wskazuje elementy, a deklaracje mówią, jak je pokazać. Gdy kilka reguł dotyczy tego samego elementu, przeglądarka musi wybrać tę, która ma pierwszeństwo. Ten mechanizm nazywamy kaskadą.
Style można podłączyć na trzy sposoby. Zewnętrzny plik przez <link rel="stylesheet" href="style.css"> jest najlepszy w większym projekcie, bo jedna poprawka działa na wszystkich stronach. Blok <style> w nagłówku nadaje się do krótkich, lokalnych reguł. Atrybut style na elemencie działa natychmiast, ale miesza treść z wyglądem i ma bardzo wysoką specyficzność.
<!-- 1. wspólny plik zewnętrzny -->
<link rel="stylesheet" href="style.css">
<!-- 2. blok stylów w nagłówku -->
<style>
p { color: #2563eb; }
</style>
<!-- 3. styl wpisany w element -->
<p style="color: #dc2626;">Akapit</p>
Selektor może wskazywać element (p), klasę (.karta), identyfikator (#wyroznik), atrybut ([type="email"]), stan (:hover, :focus) albo część elementu (::before). Selektory można łączyć: nav > a wybiera linki będące bezpośrednimi dziećmi nawigacji, a .karta p — akapity wewnątrz karty.
Gdy reguły się kłócą, przeglądarka porównuje ich specyficzność, a przy remisie — kolejność zapisu. Osobno działa dziedziczenie: niektóre właściwości, na przykład kolor tekstu, przechodzą z rodzica na dziecko, jeśli dziecko nie ma własnej reguły.
W zadaniu egzaminacyjnym i w prawdziwym projekcie trzymaj CSS w osobnym pliku. Atrybutu style używaj tylko do jednorazowego podglądu, a nie do budowy całego układu.
Najważniejsza własność
Kaskada rozstrzyga konflikt w trzech krokach. Najpierw liczy się pochodzenie i waga deklaracji, potem specyficzność selektora, a na końcu kolejność w arkuszu. W zwykłym projekcie najczęściej porównujemy właśnie specyficzność, bo wszystkie reguły pochodzą z tego samego arkusza autora.
inline 1000 > id 100 > klasa, atrybut, pseudo-klasa 10 > element, pseudo-element 1
Przy równych punktach wygrywa reguła zapisana później.
Punkty sumują się w obrębie jednego selektora. Zapis div.karta p ma 1 + 10 + 1 = 12 punktów, a #main .karta — 100 + 10 = 110. Kombinatory (>, +, ~, spacja) nie dodają punktów, podobnie jak uniwersalny selektor *.
| Selektor | Przykład | Punkty |
|---|---|---|
| element | p, article | 1 |
| klasa | .karta | 10 |
| atrybut | [type="email"] | 10 |
| pseudo-klasa | :hover, :focus | 10 |
| identyfikator | #wyroznik | 100 |
| styl inline | style="color: #dc2626;" | 1000 |
| uniwersalny | * | 0 |
Deklaracja z !important wygrywa ze zwykłymi deklaracjami, nawet jeśli te mają identyfikator. Gdy dwie deklaracje są oznaczone jako ważne, znów rozstrzyga specyficzność. To narzędzie awaryjne: utrudnia późniejsze poprawki i zaciemnia obraz kaskady, więc stosuj je wyjątkowo.
p { color: #2563eb; } /* 1 pkt */
.uwaga { color: #16a34a; } /* 10 pkt */
#glowny { color: #7c3aed; } /* 100 pkt */
Dla akapitu <p id="glowny" class="uwaga"> wygrywa reguła #glowny, bo 100 punktów to więcej niż 10 i 1. Kolor będzie fioletowy. Dopiero styl wpisany bezpośrednio w elemencie (1000 punktów) zmieniłby wynik na czerwony.
Dziedziczenie działa inaczej niż kaskada. Właściwości tekstowe, takie jak color, font-family i line-height, przechodzą z rodzica na dziecko. Właściwości układu, takie jak margin, padding, border i width, nie są dziedziczone. Ważna zasada: wartość odziedziczona przegrywa z każdą regułą, która bezpośrednio trafia w element — nawet z selektorem uniwersalnym o zerowej specyficzności.
Ważne — nie styluj identyfikatorem. Id zostaw do kotwic i skryptów. Do wyglądu używaj klas, bo można je powtarzać i łatwiej je nadpisać. Selektor #wyroznik ma 100 punktów i potem trudno go przewalczyć bez !important.
Most: od teorii do kodu
Policz punkty i wskaż zwycięzcę
Najpierw przewidź kolor, a potem uzupełnij tabelę punktów. To dokładnie ten rachunek, którego potrzebujesz w zadaniach z kaskadą.
Który kolor wygrywa?
przewidywanieAkapit ma identyfikator glowny i klasę uwaga. Który kolor przyjmie?
p { color: #2563eb; }
.uwaga { color: #16a34a; }
#glowny { color: #7c3aed; }
<p id="glowny" class="uwaga">Tekst</p>
Id ma 100 punktów, klasa 10, a element 1. Najwyższą specyficzność ma #glowny, więc wygrywa kolor #7c3aed.
Uzupełnij punkty specyficzności
uzupełnianie lukWybierz liczbę punktów odpowiadającą każdemu selektorowi.
p { color: #2563eb; } /* 1 pkt */
.uwaga { color: #16a34a; } /* pkt */
#glowny { color: #7c3aed; } /* pkt */
<p style="color: #dc2626;"> /* pkt */
Klasa jest warta 10 punktów, identyfikator 100, a styl inline 1000. Element ma tylko 1 punkt, dlatego w poprzednim pytaniu przegrał z klasą i id.
Przykłady
Zbuduj trzy karty. Każda ma inne oznaczenie, ale wszystkie są tym samym elementem. Sprawdź, która reguła nadaje kolor ramki i tła.
<div class="lista">
<article class="box">
<span class="tag">article</span>
<h3>Element</h3>
<p>Reguła <code>article</code> trafia w każdy taki element.</p>
</article>
<article class="box karta">
<span class="tag">.karta</span>
<h3>Klasa</h3>
<p>Reguła <code>.karta</code> działa tylko na elementy z tym atrybutem.</p>
</article>
<article class="box karta" id="wyroznik">
<span class="tag">#wyroznik</span>
<h3>Id</h3>
<p>Reguła <code>#wyroznik</code> wskazuje dokładnie jeden element.</p>
</article>
</div>
.box {
padding: 18px 20px;
border-width: 3px;
border-style: solid;
border-radius: 12px;
}
/* 1 punkt — element */
article { border-color: #2563eb; background: #eff6ff; }
/* 10 punktów — klasa */
.karta { border-color: #16a34a; background: #f0fdf4; }
/* 100 punktów — id */
#wyroznik { border-color: #7c3aed; background: #f5f3ff; }
- Reguła
articletrafia we wszystkie trzy karty, więc początkowo każda ma niebieską ramkę i jasnoniebieskie tło. - Reguła
.kartama 10 punktów i wygrywa z elementem. Dwie karty z tą klasą robią się zielone. - Reguła
#wyroznikma 100 punktów. Wygrywa z klasą, więc trzecia karta jest fioletowa. - Id nie powtarzaj na kilku elementach. Do wielokrotnego stylu używaj klasy, a id zostaw dla jednego wyjątku, kotwicy albo skryptu.
Wynik: karta elementu jest niebieska, karta klasy zielona, a karta z id fioletowa. Wygrywa reguła o najwyższej specyficzności.
Zbuduj przycisk reagujący na mysz, pole tekstowe z widocznym fokusem, cytat z ozdobnymi cudzysłowami i własny checkbox. Wszystko bez JavaScriptu.
<a class="akcja" href="#">Zapisz zmiany</a>
<input class="pole" type="text" value="ala@example.com" autofocus>
<blockquote class="cytat">Dobry styl zaczyna się od czytelnego kodu.</blockquote>
<label class="wybor">
<input type="checkbox" checked>
<span class="znacznik" aria-hidden="true"></span>
<span class="tekst">Zapamiętaj wybór</span>
</label>
.akcja:hover { background: #1d4ed8; }
.akcja:focus-visible { outline: 3px solid #f59e0b; }
.pole:focus {
border-color: #2563eb;
outline: 3px solid #bfdbfe;
}
.cytat::before {
content: "„";
position: absolute;
top: 2px;
left: 10px;
}
.cytat::after {
content: "”";
position: absolute;
right: 12px;
bottom: -4px;
}
.wybor input:checked + .znacznik {
border-color: #16a34a;
background: #16a34a;
}
.wybor input:checked + .znacznik::after {
content: "";
width: 6px;
height: 12px;
border: solid #fff;
border-width: 0 3px 3px 0;
transform: rotate(45deg) translate(-1px, -1px);
}
:hoverto pseudo-klasa. Reguła działa tylko wtedy, gdy wskaźnik znajduje się nad elementem. Nie zastępuj nią informacji, bez której strona przestaje być zrozumiała.:focuspokazuje, że element ma fokus.:focus-visiblejest bezpieczniejszy dla przycisków, bo przeglądarka pokazuje obwódkę głównie przy nawigacji klawiaturą.::beforei::afterto pseudo-elementy. Tworzą dodatkową treść przed elementem i po nim. Wymagają właściwościcontent, nawet jeśli jest to pusty napis.- Własny checkbox ukrywa oryginalny input, ale zostawia go dostępnym. Kolejny element
.znacznikrysuje kwadrat, a:checkedzmienia jego wygląd. Nie usuwaj fokusu bez zamiennika.
Wynik: przycisk ciemnieje po najechaniu, pole dostaje niebieską obwódkę, cytat ma cudzysłowy z CSS, a checkbox jest zielony i zaznaczony.
Ten sam akapit opisują cztery reguły: element, klasa, id i styl inline. Sprawdź, który kolor rzeczywiście się pokaże, i porównaj punkty.
<p id="zwyciezca" class="zdanie" style="color: #dc2626;">
Ten tekst jest czerwony, bo wygrywa styl inline.
</p>
p { color: #2563eb; } /* 1 pkt */
.zdanie { color: #16a34a; } /* 10 pkt */
#zwyciezca { color: #7c3aed; } /* 100 pkt */
/* styl inline: 1000 pkt */
- Reguła
pma 1 punkt i ustawia kolor niebieski. - Klasa
.zdaniema 10 punktów, więc wygrywa z elementem i daje kolor zielony. - Id
#zwyciezcama 100 punktów i wygrywa z klasą. Bez stylu inline tekst byłby fioletowy. - Styl inline ma 1000 punktów. To najwyższa wartość w tym pojedynku, dlatego tekst jest czerwony. Gdyby usunąć atrybut
style, wygrałoby id.
Wynik: widoczny jest kolor #dc2626 ze stylu inline. Kolejność reguł w arkuszu nie zmienia wyniku, bo różnią się specyficznością.
Most: sprawdź kod
Znajdź błędy w arkuszu stylów
Dwie linie nie zadziałają. Zaznacz je, a potem przeczytaj wyjaśnienie. Pozostałe deklaracje są poprawne.
Błędy składni w CSS
zaznaczanie błędówZaznacz linie, w których jest błąd składniowy.
-
W CSS właściwość oddziela się od wartości dwukropkiem, a nie znakiem równości. Powinno być
color: #dc2626;. -
Brakuje dwukropka po
background. Poprawnie:background: #f0fdf4;.
Spróbuj samodzielnie
Rozwiąż zadania samodzielnie, a dopiero potem rozwiń rozwiązanie. W każdym zadaniu nazwij selektor, policz punkty i sprawdź, czy nie da się zastąpić id zwykłą klasą.
Most: policz punkty
Tabela specyficzności
Uzupełnij punkty dla każdej reguły, a na końcu wpisz kolor, który zobaczy użytkownik.
Kto wygrywa w tym zestawie?
śledzenie wartościWpisz liczbę punktów dla każdej reguły. W ostatnim wierszu podaj kolor tekstu — wystarczy nazwa po polsku albo kod hex.
p { color: #2563eb; }
.uwaga { color: #16a34a; }
#glowny { color: #7c3aed; }
<p id="glowny" class="uwaga" style="color: #dc2626;">Tekst</p>
| Reguła | Punkty |
|---|---|
p | |
.uwaga | |
#glowny | |
style="..." | |
| Kolor tekstu |
Element ma 1 punkt, klasa 10, id 100, a styl inline 1000. Najwyższa wartość należy do stylu inline, więc tekst jest czerwony (#dc2626).
-
Dobierz selektory: (a) wszystkie akapity wewnątrz elementu
article, (b) tylko elementy z klasąwyroznik, (c) dokładnie jeden element z identyfikatoremstopka.Pokaż rozwiązanie
(a)
article p— element potomny, bez względu na głębokość. (b).wyroznik— kropka oznacza klasę, którą można powtórzyć na wielu elementach. (c)#stopka— krzyżyk oznacza identyfikator, który powinien wystąpić tylko raz w dokumencie.Gdyby akapit miał być bezpośrednim dzieckiem, użyłbyś
article > p. To nie to samo coarticle p, bo selektor dziecka nie zejdzie głębiej. -
Policz specyficzność selektorów:
nav a,.karta p,#main .kartaoraza[href]:hover.Pokaż rozwiązanie
nav a— dwa elementy, 2 punkty..karta p— klasa 10 i element 1, razem 11.#main .karta— id 100 i klasa 10, razem 110.a[href]:hover— element 1, atrybut 10 i pseudo-klasa 10, razem 21.Kombinator spacji nie dodaje punktów. Liczy się tylko to, co stoi po obu jego stronach.
-
Uczeń napisał
#karta { color: red; }i użyłid="karta"na pięciu kartach. Wskaż dwa problemy i popraw kod tak, aby styl działał na wszystkie karty, ale nie podnosił niepotrzebnie specyficzności.Pokaż rozwiązanie
Pierwszy problem: identyfikator musi być unikalny w dokumencie, więc nie można powtarzać
id="karta"na pięciu elementach. Drugi problem: selektor id ma 100 punktów i trudno go później nadpisać.Poprawka: zamień identyfikator na klasę. W HTML użyj
class="karta"na każdej karcie, a w CSS zapisz.karta { color: #dc2626; }. Klasa ma 10 punktów, może się powtarzać i łatwiej ją rozbudować o stan:hover. -
Kolega chce „naprawić” wygląd, dopisując
!importantdo co drugiej reguły. Wyjaśnij, dlaczego to zły pomysł, i podaj przykład sytuacji, w której!importantmoże być uzasadnione.Pokaż rozwiązanie
!importantwyrywa deklarację z normalnej kaskady. Późniejsze poprawki przestają działać, bo trzeba dodawać kolejne!important, a kod staje się trudny do przewidzenia. Zamiast tego uporządkuj selektory: usuń zbędne id, skróć ścieżki i wykorzystaj klasy.Uzasadnione użycie to mały, lokalny wyjątek, na przykład nadpisanie pojedynczej właściwości w gotowym widżecie zewnętrznym albo wymuszenie stylu w wydruku. Nawet wtedy warto dopisać komentarz, dlaczego reguła musi być ważna.
Selektor wybiera elementy, kaskada rozstrzyga konflikt, a specyficzność liczy się tak: inline 1000, id 100, klasa/atrybut/pseudo-klasa 10, element/pseudo-element 1. Przy równych punktach wygrywa reguła późniejsza. Id używaj oszczędnie, klas do stylu, a !important tylko w ostateczności.