The CSS Podcast - 015: Pseudo-classes
Załóżmy, że masz formularz rejestracji adresu e-mail i chcesz, aby pole formularza adresu e-mail miało czerwone obramowanie, jeśli zawiera nieprawidłowy adres e-mail.
Jak to zrobić?
Możesz użyć pseudoklasy CSS :invalid
, która jest jedną z wielu pseudoklas udostępnianych przez przeglądarkę.
Pseudoklasa umożliwia stosowanie stylów na podstawie zmian stanu i czynników zewnętrznych. Oznacza to, że projekt może reagować na działania użytkownika, np. na wpisanie nieprawidłowego adresu e-mail. Omówiliśmy je w module selektory, a w tym module znajdziesz więcej szczegółów na ich temat.
W przeciwieństwie do pseudoelementów, o których możesz dowiedzieć się więcej w poprzednim module, pseudoklasy odnoszą się do konkretnych stanów, w jakich może znajdować się element, a nie do ogólnego stylu części tego elementu.
Stany interaktywne
Poniższe pseudoklasy są stosowane ze względu na interakcję użytkownika ze stroną.
:hover
Jeśli użytkownik ma urządzenie wskazujące, takie jak mysz lub trackpad, i umieści kursor nad elementem, możesz użyć stanu :hover
, aby zastosować style.
To przydatny sposób na zasugerowanie, że z elementem można wejść w interakcję.
:active
Ten stan jest aktywowany, gdy użytkownik wchodzi w interakcję z elementem (np. klika go), zanim zwolni przycisk myszy. Jeśli używane jest urządzenie wskazujące, np. mysz, ten stan oznacza, że kliknięcie zostało rozpoczęte, ale nie zostało jeszcze zwolnione.
:focus
, :focus-within
i :focus-visible
Jeśli element może zostać zaznaczony, np. <button>
, możesz zareagować na ten stan za pomocą pseudoklasy :focus
.
Możesz też reagować, gdy element podrzędny Twojego elementu zostanie zaznaczony za pomocą :focus-within
.
Elementy, na których można ustawić fokus, takie jak przyciski, będą wyświetlać pierścień zaznaczenia, gdy są zaznaczone – nawet po kliknięciu. W takiej sytuacji deweloper zastosuje ten kod CSS:
button:focus {
outline: none;
}
Ten kod CSS usuwa domyślny pierścień zaznaczenia przeglądarki, gdy element zostaje zaznaczony, co stanowi problem z dostępnością dla użytkowników, którzy poruszają się po stronie internetowej za pomocą klawiatury.
Jeśli nie ma stylu zaznaczenia, użytkownicy nie będą mogli śledzić, gdzie znajduje się zaznaczenie podczas korzystania z klawisza Tab.
Za pomocą właściwości :focus-visible
możesz zastosować styl zaznaczenia, gdy element zostanie zaznaczony za pomocą klawiatury, a za pomocą reguły outline: none
możesz zapobiec temu, gdy wchodzi w interakcję z urządzeniem wskazującym.
button:focus {
outline: none;
}
button:focus-visible {
outline: 1px solid black;
}
:target
Pseudoklasa :target
wybiera element, który ma atrybut id
pasujący do fragmentu adresu URL.
Załóżmy, że masz taki kod HTML:
<article id="content">
<!-- ... -->
</article>
Style możesz dołączyć do tego elementu, gdy adres URL zawiera #content
.
#content:target {
background: yellow;
}
Jest to przydatne do wyróżniania obszarów, do których można było przejść za pomocą linku, np. głównej treści w witrynie, przy użyciu linku do pomijania.
Stany historyczne
:link
Pseudoklasę :link
można zastosować do dowolnego elementu <a>
, który ma wartość href
, która nie została jeszcze odwiedzona.
:visited
Możesz zastosować styl do linku, który został już odwiedzony przez użytkownika, za pomocą pseudoklasy :visited
.
Jest to stan przeciwny do :link
, ale z względów bezpieczeństwa masz do dyspozycji mniej właściwości CSS.
Możesz zmieniać styl elementów color
, background-color
,border-color
, outline-color
oraz kolor elementów SVG fill
i stroke
.
Kolejność spraw
Jeśli zdefiniujesz styl :visited
, może on zostać zastąpiony przez pseudoklasę linku o co najmniej takiej samej specyficzności.
Z tego powodu zalecamy używanie reguły LVHA do stylizowania linków za pomocą pseudoklas w określonej kolejności: :link
, :visited
, :hover
, :active
.
a:link {}
a:visited {}
a:hover {}
a:active {}
Stany formularza
Poniższe pseudoklasy mogą wybierać elementy formularza w różnych stanach, w jakich mogą się one znajdować podczas interakcji z nimi.
:disabled
i :enabled
Jeśli element formularza, np. <button>
, jest wyłączony przez przeglądarkę, możesz skorzystać z pseudoklasy :disabled
, aby uzyskać dostęp do tego stanu.
Klasa :enabled
jest dostępna dla stanu przeciwnego, ale elementy formularza są też domyślnie :enabled
, więc możesz nie potrzebować tej klasy.
:checked
i :indeterminate
Pseudoklasa :checked
jest dostępna, gdy obsługujący element formularza, taki jak pole wyboru lub przycisk opcji, jest zaznaczony.
Stan :checked
jest stanem binarnym (prawda lub fałsz), ale pola wyboru mają stan pośredni, gdy nie są zaznaczone ani odznaczone.
Jest to tzw. stan :indeterminate
.
Przykładem takiego stanu jest sytuacja, w której masz element sterujący „Zaznacz wszystko”, który zaznacza wszystkie pola wyboru w grupie. Jeśli użytkownik odznaczy jedno z tych pól wyboru, główne pole wyboru nie będzie już oznaczać, że „wszystkie” są zaznaczone, więc powinno przejść w stan nieokreślony.
Element <progress>
ma też stan nieokreślony, który można ostylować.
Często stosuje się paski, aby wskazać, że nie wiadomo, ile jeszcze brakuje.
:placeholder-shown
Jeśli pole formularza ma atrybut placeholder
i nie ma wartości, dołączenie stylów do tego stanu jest możliwe za pomocą pseudoklasy :placeholder-shown
.
Gdy tylko w polu pojawią się treści, niezależnie od tego, czy mają one wartość placeholder
, ten stan przestanie obowiązywać.
Stany weryfikacji
Na walidację formularza HTML możesz odpowiadać za pomocą pseudoklas, takich jak :valid
, :invalid
i :in-range
.
Pseudoklasy :valid
i :invalid
są przydatne w kontekstach, takich jak pole adresu e-mail, które ma znak pattern
, który musi być dopasowany, aby pole było prawidłowe.
Ten stan prawidłowej wartości może być wyświetlany użytkownikowi, co pomoże mu zrozumieć, że może bezpiecznie przejść do następnego pola.
Klasa pseudoelementu :in-range
jest dostępna, jeśli dane wejściowe mają atrybuty min
i max
, np. dane liczbowe i wartość mieści się w tych granicach.
W przypadku formularzy HTML możesz określić, że pole jest wymagane, za pomocą atrybutu required
.
Klasa pseudoelementu :required
będzie dostępna w przypadku wymaganych pól.
Pola, które nie są wymagane, można wybrać za pomocą pseudoklasy :optional
.
Wybieranie elementów według indeksu, kolejności i występowania
Istnieje grupa pseudoklas, które wybierają elementy na podstawie ich położenia w dokumencie.
:first-child
i :last-child
Jeśli chcesz znaleźć pierwszy lub ostatni element, możesz użyć
:first-child
i
:last-child
.
Te pseudoklasy zwracają pierwszy lub ostatni element w grupie elementów pokrewnych.
:only-child
Możesz też wybrać elementy, które nie mają elementów równorzędnych, za pomocą pseudoklasy :only-child
.
:first-of-type
i :last-of-type
Możesz wybrać tagi :first-of-type
i :last-of-type
, które na pierwszy rzut oka działają tak samo jak tagi :first-child
i :last-child
, ale weź pod uwagę ten kod HTML:
<div class="my-parent">
<p>A paragraph</p>
<div>A div</div>
<div>Another div</div>
</div>
A ta usługa porównywania cen:
.my-parent div:first-child {
color: red;
}
Żaden element nie będzie czerwony, ponieważ pierwszym elementem podrzędnym jest akapit, a nie element div. W tym kontekście przydatna jest pseudoklasa :first-of-type
.
.my-parent div:first-of-type {
color: red;
}
Chociaż pierwszy element <div>
jest drugim elementem podrzędnym, jest on pierwszym elementem tego typu w elemencie .my-parent
, więc zgodnie z tą regułą będzie miał kolor czerwony.
:nth-child
i :nth-of-type
Nie musisz ograniczać się do pierwszych i ostatnich elementów podrzędnych ani typów.
Pseudoklasy :nth-child
i :nth-of-type
umożliwiają określenie elementu, który znajduje się pod określonym indeksem.
Indeksowanie w selektorach CSS zaczyna się od 1.
Pseudoklasy :nth-last-child()
i :nth-last-of-type()
liczą od końca, a nie od początku.
Do tych pseudoklas możesz też przekazywać więcej niż tylko indeks.
Jeśli chcesz wybrać wszystkie elementy parzyste, możesz użyć :nth-child(even)
.
Możesz też tworzyć bardziej złożone selektory, które znajdują elementy w regularnych odstępach, używając mikroskładni An+B.
li:nth-child(3n+3) {
background: yellow;
}
Ten selektor wybiera co trzeci element, począwszy od elementu 3.
Znak n
w tym wyrażeniu to indeks, który zaczyna się od zera, a 3 (3n
) to liczba, przez którą mnożysz ten indeks.
Załóżmy, że masz 7 <li>
.
Pierwszym wybranym elementem jest 3, ponieważ 3n+3
przekłada się na (3 * 0) + 3
.
W kolejnej iteracji zostanie wybrany element 6, ponieważ wartość n
wzrosła do 1
, a więc (3 * 1) + 3)
.
To wyrażenie działa zarówno w przypadku :nth-child
, jak i :nth-of-type
.
:nth-child()
i :nth-last-child()
obsługują też składnię „of S”, która umożliwia filtrowanie dopasowań za pomocą selektora, podobnie jak :nth-of-type()
. Funkcja li:nth-of-type(even)
jest odpowiednikiem funkcji :nth-child(even of li)
. O ile :nth-of-type
pozwala filtrować tylko według typu elementu (np. li
lub p
), składnia „of S” umożliwia filtrowanie według dowolnego selektora.
Jeśli masz tabelę, możesz dodać paski do co drugiego wiersza. Możesz kierować reklamy na co drugi wiersz za pomocą funkcjitr:nth-child(even)
, ale nie działa to, jeśli filtrujesz niektóre wiersze. Jeśli filtrujesz, stosując atrybut hidden
, możesz dodać of :not([hidden])
do selektora, aby wstępnie odfiltrować ukryte elementy przed wybraniem parzystych wierszy.
tr:nth-child(even of :not([hidden])){
background: lightgrey;
}
Możesz wypróbować ten rodzaj selektora w tym testerze selektora nth-child lub tym narzędziu do wyboru ilości.
:only-of-type
Możesz też znaleźć jedyny element określonego typu w grupie elementów równorzędnych za pomocą selektora :only-of-type
.
Jest to przydatne, jeśli chcesz wybrać listy z tylko jednym elementem lub znaleźć jedyny element w tekście, który jest pogrubiony.
Wyszukiwanie pustych elementów
Czasami przydatne może być zidentyfikowanie całkowicie pustych elementów. W tym celu również istnieje pseudoklasa.
:empty
Jeśli element nie ma elementów podrzędnych, stosuje się do niego pseudoklasę :empty
.
Elementy podrzędne to nie tylko elementy HTML czy węzły tekstowe, ale też białe znaki, co może być mylące podczas debugowania poniższego kodu HTML i zastanawiania się, dlaczego nie działa on z funkcją :empty
:
<div>
</div>
Dzieje się tak, ponieważ między otwierającym i zamykającym znakiem <div>
jest trochę białych znaków, więc :empty
nie będzie działać.
Klasa pseudo :empty
może być przydatna, jeśli masz niewielką kontrolę nad kodem HTML i chcesz ukryć puste elementy, np. edytor treści WYSIWYG.
W tym przypadku osoba edytująca dodała niepotrzebny pusty akapit.
<article class="post">
<p>Donec ullamcorper nulla non metus auctor fringilla.</p>
<p></p>
<p>Curabitur blandit tempus porttitor.</p>
</article>
Dzięki :empty
możesz znaleźć i ukryć takie informacje.
.post :empty {
display: none;
}
Znajdowanie i wykluczanie wielu elementów
Niektóre pseudoklasy pomagają pisać bardziej zwięzły kod CSS.
:is()
Jeśli chcesz znaleźć wszystkie elementy podrzędne h2
, li
i img
w elemencie .post
, możesz napisać taką listę selektorów:
.post h2,
.post li,
.post img {
…
}
Za pomocą pseudoklasy :is()
możesz napisać bardziej zwięzłą wersję:
.post :is(h2, li, img) {
/* ... */
}
Pseudoklasa :is
jest nie tylko bardziej zwarta niż lista selektorów, ale też bardziej tolerancyjna.
W większości przypadków, jeśli na liście selektorów wystąpi błąd lub nieobsługiwany selektor, cała lista selektorów przestanie działać.
Jeśli w pseudoklasie :is
wystąpi błąd w przekazanych selektorach, zignoruje on nieprawidłowy selektor, ale użyje tych, które są prawidłowe.
:not()
Możesz też wykluczyć elementy za pomocą pseudoklasy :not()
.
Możesz na przykład użyć go do określenia stylu wszystkich linków, które nie mają atrybutu class
.
a:not([class]) {
color: blue;
}
:not
Klasa pseudoelementu może też pomóc w zwiększeniu dostępności.
Na przykład element <img>
musi mieć element alt
, nawet jeśli jest to pusta wartość. Możesz więc napisać regułę CSS, która dodaje gruby czerwony kontur do nieprawidłowych obrazów:
img:not([alt]) {
outline: 10px red;
}
:has()
Co zrobić, jeśli chcesz zastosować styl do elementów na podstawie tego, co zawierają? Możesz do tego użyć pseudoklasy :has()
. Możesz na przykład zastosować style do przycisków zawierających ikony.
button:has(svg) {
/* ... */
}
W najprostszej konfiguracji, takiej jak w poprzednim przykładzie, :has()
można traktować jako selektor nadrzędny. Możesz też użyć selektora pasującego elementu nadrzędnego w połączeniu z innymi selektorami, aby kierować reklamy na inne elementy.
form:has(input:valid) label {
font-weight: bold;
}
form:has(input:valid) label::after {
content: "✅";
}
W tym przykładzie stosujemy style do elementu etykiety i pseudoelementu label::after
, gdy element wejściowy formularza ma pseudoklasę valid
.
Klasy pseudo :has()
nie można zagnieżdżać w innej klasie :has()
, ale można ją łączyć z innymi klasami pseudo.
:is(h1, h2, h3):has(a) {
/* ... */
}
Lista selektorów jest bezwzględna, więc jeśli którykolwiek selektor na liście jest nieprawidłowy, wszystkie reguły stylu zostaną zignorowane.
.my-element:has(img, ::before) {
/* any styles here will be discarded since pseudo elements can't be included in the :has() selector list */
}
Sprawdź swoją wiedzę
Sprawdź swoją wiedzę o klasach pozornych
Pseudoklasy działają tak, jakby do elementu została dynamicznie zastosowana klasa, a pseudoelementy działają na samym elemencie.
:
jako kluczowego znaku rozróżniającego w selektorze.Które z poniższych są funkcyjnymi pseudoklasami?
:is()
:target
()
, co oznacza, że przyjmują one parametry.:empty
()
, co oznacza, że przyjmują one parametry.:not()
Które z tych pseudoklas są wynikiem interakcji użytkownika?
:hover
:press
:squeeze
:target
:focus-within
Które z tych elementów są pseudoklasami stanu <form>
?
:enabled
:fresh
:indeterminate
:checked
:in-range
:loading
:valid