Lekcja 30

Kaskada, specyficzność i @layer

CSS jest kaskadowy: wiele reguł może dotyczyć tego samego elementu, a przeglądarka musi zdecydować, która deklaracja wygra. W tej lekcji uporządkujesz mentalny model kaskady i poznasz @layer jako narzędzie do kontroli kolejności stylów w większym projekcie.

Cele lekcji

Po ukończeniu tej lekcji będziesz umieć:

  • wyjaśnić, czym jest kaskada CSS,
  • ocenić podstawową specyficzność selektorów,
  • zrozumieć rolę kolejności reguł w arkuszu,
  • unikać eskalacji przez !important,
  • rozpoznać wpływ stylów inline,
  • używać @layer do porządkowania resetu, baz, komponentów i utilities.

Kontekst praktyczny

Problemy z kaskadą zaczynają się wtedy, gdy komponent trzeba nadpisać coraz mocniejszym selektorem. Najpierw pojawia się .card .title, potem .page .card .title, a na końcu !important. To zwykle sygnał, że projekt potrzebuje lepszego porządku warstw i niższej specyficzności.

W praktyce: senior developer nie wygrywa z kaskadą siłą. Projektuje kolejność stylów tak, aby nadpisywanie było przewidywalne.

Czym jest kaskada

Kaskada to zestaw zasad, które decydują, która deklaracja CSS zostanie zastosowana. Znaczenie mają między innymi: źródło stylu, warstwa, specyficzność selektora, kolejność w arkuszu oraz !important.

.button {
  background: #2563eb;
}

.button {
  background: #16a34a;
}

Jeżeli dwie reguły mają tę samą siłę, wygrywa deklaracja zapisana później. W przykładzie przycisk dostanie zielone tło.

Specyficzność

Specyficzność określa, jak mocny jest selektor. ID jest mocniejsze niż klasa, a klasa jest mocniejsza niż selektor elementu. Im bardziej rozbudowany selektor, tym trudniej go później nadpisać.

button {
  color: #475569;
}

.button {
  color: #2563eb;
}

#primary-action {
  color: #dc2626;
}

W tym zestawie selektor ID wygra, nawet jeśli znajduje się wcześniej niż klasa. Dlatego ID rzadko jest dobrym wyborem do codziennego stylowania komponentów.

Kolejność źródła

Kiedy specyficzność jest taka sama, wygrywa reguła późniejsza. To prosty mechanizm, ale w dużym projekcie łatwo go zepsuć przez przypadkowe importy albo chaotyczną kolejność plików.

/* components.css */
.alert {
  border-color: #bfdbfe;
}

/* utilities.css loaded later */
.alert {
  border-color: #fca5a5;
}

Jeśli utilities mają być łatwe do nadpisywania komponentów, powinny być ładowane później albo umieszczone w późniejszej warstwie.

Important i inline

!important zmienia normalną kolejność rozstrzygania deklaracji. Style inline są bardzo mocne i zwykle powinny być używane ostrożnie, szczególnie gdy później chcesz kontrolować wygląd z arkusza CSS.

.badge {
  color: #2563eb !important;
}

<span class="badge" style="color: #dc2626;">
  Status
</span>

!important bywa potrzebne w klasach utility albo wyjątkach dostępnościowych, ale używane bez kontroli prowadzi do wojny deklaracji.

Podstawy @layer

@layer pozwala jawnie określić kolejność grup stylów. Dzięki temu reset, style bazowe, komponenty i utility mogą mieć przewidywalną hierarchię bez podbijania specyficzności.

@layer reset, base, components, utilities;

@layer components {
  .button {
    padding: .75rem 1rem;
  }
}

Kolejność podana w pierwszej deklaracji jest ważna. Warstwa zapisana później w tej liście ma większy priorytet niż wcześniejsza.

Kolejność warstw

Warstwy pomagają uniknąć selektorów typu .page .section .card .button. Utility może wygrać z komponentem, bo jest w późniejszej warstwie, nawet jeśli ma prostszy selektor.

@layer components {
  .button {
    background: #2563eb;
  }
}

@layer utilities {
  .u-bg-success {
    background: #16a34a;
  }
}

Jeśli utilities jest późniejszą warstwą niż components, klasa .u-bg-success może wygrać bez selektora o większej specyficzności.

Demo kaskady

Demo pokazuje różnicę między chaotycznym nadpisywaniem i uporządkowanymi warstwami. W obu przypadkach efekt może wyglądać podobnie, ale koszt utrzymania jest zupełnie inny.

Bez warstw

Rosnąca specyficzność

.page .card .button

Każde nadpisanie wymaga mocniejszego selektora albo kolejnego wyjątku.

  1. elementbutton
  2. klasa.button
  3. łańcuch.page .card .button
@layer

Jawna kolejność

@layer components, utilities

Proste selektory działają, bo kolejność warstw jest częścią architektury.

  1. reset@layer reset
  2. komponent@layer components
  3. utility@layer utilities

Najczęstsze błędy początkujących

  • Dodawanie coraz dłuższych selektorów zamiast zmniejszenia specyficzności.
  • Nadużywanie ID do stylowania komponentów.
  • Używanie !important jako pierwszego sposobu naprawy.
  • Ładowanie plików CSS w przypadkowej kolejności.
  • Mieszanie resetu, komponentów i utilities w jednej nieuporządkowanej warstwie.
  • Zakładanie, że @layer zastępuje dobre nazwy klas i czytelną strukturę plików.

Mini zadanie

Uporządkuj style dla przycisku w małym systemie UI.

  • Zdefiniuj kolejność warstw: reset, base, components, utilities.
  • Umieść bazowy styl .button w warstwie components.
  • Dodaj utility .u-bg-success w warstwie utilities.
  • Sprawdź, czy utility wygrywa bez !important.
  • Usuń zbyt długi selektor, jeśli możesz zastąpić go warstwą albo prostszą klasą.

Checklista

  • Rozumiem, że kaskada decyduje, która deklaracja CSS wygrywa.
  • Potrafię porównać specyficzność elementu, klasy i ID.
  • Wiem, kiedy kolejność źródła ma znaczenie.
  • Używam !important świadomie i rzadko.
  • Potrafię zaplanować podstawową kolejność warstw przez @layer.
  • Nie podbijam specyficzności, gdy problemem jest organizacja arkusza.

Podsumowanie lekcji

Kaskada nie jest błędem CSS, tylko jego podstawowym mechanizmem. Specyficzność, kolejność źródła, !important i @layer trzeba rozumieć jako narzędzia kontroli. Dobrze zaprojektowane warstwy pozwalają pisać prostsze selektory i ograniczają chaos w większym projekcie.

Kolejny krok roadmapy to reset, normalize i style bazowe.

Przejdź do Lekcji 31