Lekcja 33
Pseudoklasy i pseudoelementy w praktyce
Pseudoklasy pozwalają stylować elementy zależnie od stanu, relacji albo pozycji w strukturze. Pseudoelementy pozwalają stylować fragmenty elementu albo dodać dekorację bez dokładania kolejnego znacznika HTML.
Cele lekcji
Po ukończeniu tej lekcji będziesz umieć:
- stosować pseudoklasy stanów, takie jak
:hover,:focus-visiblei:disabled, - używać pseudoklas strukturalnych do stylowania list i powtarzalnych elementów,
- grupować selektory przez
:is()i obniżać specyficzność przez:where(), - wykluczać elementy przez
:not(), - stylować stany formularzy przez
:required,:validi:invalid, - używać
::beforei::afterdo dekoracji bez utraty semantyki.
Kontekst praktyczny
W realnym interfejsie wiele decyzji zależy od stanu: link jest odwiedzony, przycisk ma fokus, pole formularza jest niepoprawne, a ostatni element listy nie powinien mieć separatora. Pseudoklasy i pseudoelementy pozwalają opisać te sytuacje bez dokładania klas do każdego przypadku.
Stany UI
Pseudoklasy stanów opisują interakcję użytkownika z elementem. Najczęściej używasz ich przy linkach, przyciskach, kartach i polach formularza.
.button:hover {
background: #1d4ed8;
}
.button:focus-visible {
outline: 3px solid #93c5fd;
outline-offset: 3px;
}
.button:disabled {
opacity: .55;
cursor: not-allowed;
}
:focus-visible jest lepsze od prostego :focus dla wielu komponentów, bo pokazuje fokus głównie wtedy, gdy jest potrzebny użytkownikowi klawiatury.
Pseudoklasy strukturalne
Pseudoklasy strukturalne wybierają elementy na podstawie ich miejsca w dokumencie. Są przydatne przy listach, tabelach, kartach i separatorach.
.list-item:first-child {
border-top: 0;
}
.list-item:last-child {
border-bottom: 0;
}
.table-row:nth-child(even) {
background: #f8fafc;
}
Używaj ich do wzorców wynikających ze struktury. Jeżeli konkretny element ma znaczenie produktowe, nazwij go klasą zamiast liczyć jego pozycję.
:is() i :where()
:is() upraszcza grupowanie selektorów. :where() robi podobną rzecz, ale ma zerową specyficzność, co pomaga pisać style bazowe łatwe do nadpisania.
.card :is(h2, h3, p) {
margin: 0;
}
:where(.content) :where(ul, ol) {
padding-left: 1.25rem;
}
W praktyce :where() dobrze pasuje do warstwy base i layout, a :is() do czytelnego skracania selektorów komponentów.
:not()
:not() wybiera elementy, które nie pasują do podanego selektora. Przydaje się do wyjątków strukturalnych, ale łatwo go nadużyć.
.nav-link:not([aria-current="page"]) {
color: #475569;
}
.stack > *:not(:last-child) {
margin-bottom: 1rem;
}
Jeśli :not() robi się długie albo opisuje wiele warunków naraz, prawdopodobnie potrzebujesz klasy wariantu albo prostszej struktury HTML.
Pseudoklasy formularzy
Formularze mają własne pseudoklasy stanów. Możesz reagować na wymagane pola, poprawne wartości, błędy, disabled i checked bez ręcznego dokładania klas do każdego pola.
.field input:required {
border-color: #93c5fd;
}
.field input:invalid {
border-color: #f87171;
}
.field input:valid {
border-color: #86efac;
}
Pamiętaj, że walidacja CSS nie zastępuje komunikatów błędu i logiki formularza. To tylko warstwa wizualnego feedbacku.
Pseudoelementy
Pseudoelementy pozwalają stylować część elementu albo dodać dekoracyjny fragment. Najczęściej spotkasz ::before, ::after, ::marker, ::selection i ::first-letter.
.badge::before {
content: "";
width: .5rem;
height: .5rem;
border-radius: 999px;
background: #22c55e;
}
::selection {
background: #bfdbfe;
}
Treść dodawana przez content powinna być dekoracyjna. Ważnych informacji nie ukrywaj wyłącznie w ::before albo ::after.
Demo selektorów
Demo pokazuje pseudoklasy i pseudoelementy w małym komponencie zadania. Są tu stany przycisków, marker statusu bez dodatkowego elementu oraz strukturalne separatory listy.
Przegląd komponentu
Najedź na akcję albo przejdź klawiaturą, aby zobaczyć stan interakcji.
Lista kontrolna
- :first-childusuwa zbędny separator startowy
- :not()pomija element aktywny albo ostatni
- ::beforedodaje dekoracyjny status
- ::markerstyluje numer listy
Najczęstsze błędy początkujących
- Usuwanie stylu fokusu bez zapewnienia dostępnej alternatywy.
- Używanie
:hoverjako jedynego feedbacku interakcji. - Opieranie logiki komponentu na
:nth-child(), gdy potrzebna jest klasa wariantu. - Tworzenie bardzo długich selektorów z
:not(). - Dodawanie ważnej treści przez
::beforealbo::after. - Zapominanie, że
:where()ma zerową specyficzność i łatwo je nadpisać.
Mini zadanie
Zbuduj mały komponent listy zadań z pseudoklasami i pseudoelementami.
- Dodaj link lub przycisk ze stanami
:hover,:focus-visiblei:disabled. - Użyj
:not(:last-child)do separatorów między zadaniami. - Użyj
:is(), aby skrócić selektor nagłówków i akapitów wewnątrz karty. - Dodaj dekoracyjny status przez
::before. - W formularzu testowym ostyluj
:required,:validi:invalid. - Sprawdź, czy ważna informacja jest nadal dostępna w HTML, a nie tylko w pseudoelementach.
Checklista
- Rozumiem różnicę między pseudoklasą i pseudoelementem.
- Potrafię zaprojektować widoczny stan
:focus-visible. - Używam pseudoklas strukturalnych tylko wtedy, gdy wynikają ze struktury.
- Wiem, kiedy użyć
:is(), a kiedy:where(). - Nie wkładam kluczowej treści do
::beforeani::after. - Potrafię ostylować podstawowe stany formularza bez dodatkowych klas.
Podsumowanie lekcji
Pseudoklasy i pseudoelementy pozwalają pisać mniej klas, ale wymagają dobrego wyczucia. Stany interakcji, pozycja w strukturze i dekoracyjne elementy CSS powinny wspierać semantyczny HTML, a nie go zastępować.
Kolejny krok roadmapy to container queries.
Przejdź do Lekcji 34