Listy CSS, znaczniki i liczniki
Opublikowany: 2022-03-10 Listy w CSS mają określone właściwości, które dają nam standardową stylizację list, jakiej oczekujemy. Lista nieuporządkowana otrzymuje punktor listy typu disc
, a listy uporządkowane są numerowane. Moje zainteresowanie bardziej szczegółowym badaniem list wzięło się z pracy, którą wykonałem, aby udokumentować pseudoelement ::marker
dla MDN. Ten pseudoelement jest dostarczany w Firefoksie 68 i jest wypuszczany dzisiaj . Mając dostępny pseudoelement ::marker
, możemy zacząć robić ciekawe rzeczy z listami, a w tym artykule wyjaśnię więcej.
Dekonstruowanie listy
Być może nie myślałeś zbyt wiele o listach, chociaż często używamy ich w naszych znacznikach. Wiele rzeczy można oznaczyć dość logicznie jako listę. Podczas gdy instrukcje krok po kroku lub elementy uszeregowane mogą być naturalnie opisane za pomocą uporządkowanej listy <ol>
, wiele rzeczy w projekcie można opisać za pomocą nieuporządkowanej listy <ul>
. Bardzo powszechnym zastosowaniem tego elementu jest na przykład oznaczenie nawigacji, ponieważ jest to lista miejsc docelowych na stronie. Na potrzeby naszej eksploracji zacznijmy od dokładnego sprawdzenia, czym jest lista w CSS.
Podobnie jak w przypadku wielu rzeczy w CSS, do list przypisane są pewne wartości początkowe. Te wartości sprawiają, że wyglądają jak lista. Te specjalne wartości zaczynają się od informacji, że element listy ma właściwość display
z wartością list-item
. Tworzy to pole na poziomie bloku z dodatkowym polem znacznika. Pole znacznika to miejsce, w którym dodawany jest punktor listy lub numer.
Listy zostały zdefiniowane na wczesnym etapie w CSS, a większość definicji list, jakich używamy dzisiaj, pochodzi z CSS2. Specyfikacja CSS2 opisuje element listy w następujący sposób:
„Element zdisplay: list-item
generuje pole bloku głównego dla zawartości elementu i, w zależności od wartościlist-style-type
ilist-style-image
, prawdopodobnie również pole znacznika jako wizualne wskazanie, że element jest element listy”.
Główne pole blokowe jest głównym polem elementu i zawiera wszystkie elementy potomne, ponieważ element listy może zawierać inne znaczniki. Pole znacznika jest następnie umieszczane w odniesieniu do tego pola głównego. W specyfikacji szczegółowo opisano, że każdy kolor tła będzie znajdował się tylko za tym głównym polem, a nie za znacznikiem. Ponadto znacznik można ustawić na jedną z zakresu wstępnie zdefiniowanych wartości:
-
disc
-
circle
-
square
-
decimal
-
decimal-leading-zero
-
lower-roman
-
upper-roman
-
lower-greek
-
lower-latin
-
upper-latin
-
armenian
-
georgian
-
lower-alpha
-
upper-alpha
-
none
-
inherit
Specyfikacja wyświetlania poziomu 3 definiuje display: list-item
wraz z innymi możliwymi wartościami właściwości display
. Odwołuje się do CSS 2.1 — podobnie jak wiele właściwości i wartości CSS pochodzących z CSS2 — ale opisuje słowo kluczowe list-item
jako „powodujące, że element generuje pseudoelement ::marker
”.
Specyfikacja poziomu 3 wprowadza również możliwość tworzenia wbudowanego elementu listy z dwiema używanymi składniami wartości display: inline list-item
. Jest to jeszcze niezaimplementowane przez przeglądarki.
Tworzenie pól znaczników na elementach spoza listy
Podobnie jak w przypadku innych wartości display
, jest całkowicie poprawne nadanie każdemu elementowi HTML typu wyświetlania elementu list-item
(jeśli chcesz wygenerować pseudoelement ::marker
na elemencie). Nie spowoduje to, że element stanie się semantycznie elementem listy, ale zamiast tego będzie wyświetlany tylko wizualnie jako element listy, a zatem będzie mógł mieć ::marker
. Kiedy omówimy poniżej pseudoelement ::marker
, odkryjesz kilka przypadków, w których podanie innych elementów display: list-item
może być przydatne.
Specyfikacja list CSS na poziomie 3: ::marker
i liczniki
Specyfikacja display
rozszerza i wyjaśnia definicję list, którą można znaleźć w CSS2, jednak istnieje również specyfikacja, która szczegółowo definiuje zachowanie list: CSS Lists Specification Level 3. Ponieważ podstawowe zachowanie elementów list jest zdefiniowane w display
, to specyfikacja wyszczególnia pole znacznika wygenerowane, gdy coś ma display: list-item
wraz z licznikami, które są używane domyślnie, gdy tworzysz uporządkowaną listę. Istnieje kilka potencjalnie przydatnych funkcji, do których można uzyskać dostęp za pośrednictwem tych funkcji.
::marker
::marker
umożliwia namierzenie znacznika listy — niezależnie od zawartości elementu listy. Nie było to możliwe w poprzednich wersjach CSS, dlatego jeśli zmieniłeś kolor lub rozmiar czcionki ul
lub li
, zmieniłoby to również kolor i rozmiar czcionki znaczników. Aby zrobić coś tak pozornie prostego, jak posiadanie punktorów listy w innym kolorze niż tekst, wymagałoby to zawinięcia zawartości elementu listy w rozpiętość (lub użycia obrazu jako znacznika).
ul { color: #00b7a8; } ul span { color #333; }
W przypadku pseudoelementu ::marker
najprostszą rzeczą, którą możesz chcieć wypróbować, jest użycie innego koloru punktora na tekst, co oznacza, że zamiast kodu z powyższego przykładu możesz użyć:
ul { color: #333; } ul ::marker { color: #00b7a8; }
Możesz również użyć innego rozmiaru i font-family
do numerowania na uporządkowanej liście.
ol ::marker { font-size: 200%; color: #00b7a8; font-family: "Comic Sans MS", cursive, sans-serif; }
Możesz zobaczyć to wszystko w obsługiwanej przeglądarce, używając mojego przykładu CodePen:
Możesz użyć pseudoelementu ::marker
na elementach spoza listy. W poniższym kodzie ustawiłem nagłówek do display: list-item
. Daje mu to punktor, a tym samym pole ::marker
do celu.
Zmieniłem punktor, aby używał emoji:
h1 { display: list-item; } h1::marker { content: ""; }
W powyższym przykładzie użyłem wygenerowanej treści w regułach znacznika. Tylko niewielki podzbiór właściwości CSS jest dostępny do użycia w ::marker
. Obejmują one właściwości czcionki i kolor, jednak obejmują one również właściwość content
, umożliwiającą uwzględnienie wygenerowanej treści.
Dodanie content
jako dozwolonej właściwości dla ::marker
jest niedawne, jednak zostało uwzględnione w implementacji Firefoksa. Włączenie oznacza, że możesz na przykład umieścić ciąg tekstu w ::marker
. Daje również dodatkowe możliwości formatowania znaczników, gdy połączysz użycie liczników z ::marker
.
Obsługa przeglądarek i awaryjne
W przypadku przeglądarek, które nie obsługują pseudoelementu ::marker
, rezerwą zastępczą jest zwykły znacznik, który i tak zostałby wyświetlony. Niestety, nie możemy obecnie używać zapytań o funkcje do wykrywania obsługi selektorów, takich jak ten pseudoelement, chociaż pojawił się problem z dodaniem tego do specyfikacji. Oznacza to, że nie możesz rozwidlić swojego kodu, aby robił jedną rzecz, gdy masz wsparcie, a coś innego, jeśli nie masz. W większości przypadków rozsądnym rozwiązaniem będzie powrót do zwykłego markera.
Liczniki
Listy uporządkowane mają numerację list — coś, co uzyskuje się za pomocą licznika CSS. Dlatego specyfikacja list CSS opisuje również te liczniki. Sami możemy uzyskać dostęp do liczników i tworzyć je, co w połączeniu z pseudoelementem ::marker
może dać nam pewną użyteczną funkcjonalność. Liczniki te mogą być również używane w zwykłych (nie ::marker
) treściach generowanych.
Jeśli mam ponumerowaną listę kroków (i chciałbym napisać „Krok 1”, „Krok 2” i tak dalej), mogę to zrobić, używając wygenerowanej treści w moim znaczniku i dołączając licznik list-item
, reprezentuje to wbudowany licznik:
::marker { content: "Step " counter(list-item) ": "; }
Zagnieżdżone liczniki
Jeśli masz listy zagnieżdżone, powszechnym sposobem ich numerowania jest umieszczenie elementu najwyższego poziomu w liczbie całkowitej (1), a następnie elementów podrzędnych (1.1, 1.2) i ich dzieci (1.1.1, 1.1.2), i tak dalej. Możesz to osiągnąć, wykorzystując większą funkcjonalność liczników.
Kiedy zagnieżdżasz listy HTML, otrzymasz wiele liczników o tej samej nazwie — zagnieżdżonych w sobie. Dostęp do gniazda liczników można uzyskać za pomocą funkcji counters()
.
W poniższym kodzie używam counters()
do formatowania moich znaczników listy, jak opisano powyżej. Pierwszym argumentem dla counters()
jest nazwa używanego licznika. Używam wbudowanego licznika list-item
. Drugim argumentem jest łańcuch — to jest to, co zostanie połączone między licznikami wyjściowymi (używam .
). Na koniec dodaję :
poza funkcją licznika, ale wewnątrz wartości content
, aby moje wyjście licznika było oddzielone od zawartości dwukropkiem.
::marker { content: counters(list-item,'.') ':'; color: #00b7a8; font-weight: bold; }
Daje mi to wyjście jak na obrazku. Jeśli używasz przeglądarki, która obsługuje ::marker
i liczniki, możesz zobaczyć, jak działa w przykładzie CodePen — spróbuj zmienić ciąg z a .
do czegoś innego, aby zobaczyć, jak zmienia to wyjście.
Jaka jest różnica między counter()
a counters()
?
Funkcja counter()
, której użyliśmy w pierwszym przykładzie do wypisania naszych kroków, używa tylko najbardziej wewnętrznego licznika. Dlatego w sytuacji, gdy masz zestaw list zagnieżdżonych, wypiszesz licznik, który odnosił się do poziomu, na którym aktualnie się znajdujesz.
Funkcja counters()
zasadniczo zapisuje całą gałąź i daje możliwość łączenia łańcucha między licznikami w gałęzi. Jeśli więc masz element listy z licznikiem 2
(który jest częścią listy zagnieżdżonej wewnątrz elementu listy z licznikiem 4
), gałąź zawiera:
-
4
-
2
Możesz wyprowadzić to jako 4.2
w znaczniku, używając:
::marker { content: counters(list-item,'.'); }
Liczniki na innych elementach
Liczniki mogą być używane do rzeczy, które nie są listami — albo do wyprowadzania znacznika — w takim przypadku element będzie musiał mieć display: list-item
— lub do wyprowadzenia zwykłej wygenerowanej zawartości. Liczniki są szeroko stosowane w produkcji książek, w celu umożliwienia numerowania rozdziałów i cyfr oraz innych rzeczy. Nie ma powodu, aby nie stosować podobnego podejścia w sieci, zwłaszcza w przypadku dłuższych artykułów.
Właściwości CSS zdefiniowane w specyfikacji List CSS, które dotyczą tych liczników, to:
-
counter-set
-
counter-reset
-
counter-increment
Aby zobaczyć, jak działają one poza listami, przyjrzyjmy się przykładowi użycia liczników do numerowania nagłówków w dokumencie.
Pierwszą rzeczą, którą muszę zrobić, to utworzyć licznik nagłówków na elemencie body — gotowy do użycia. W tym celu używam właściwości counter-reset
. Właściwości counter-reset
i counter-set
są bardzo podobne. Właściwość counter-reset
utworzy nowy licznik, jeśli licznik o określonej nazwie jeszcze nie istnieje, ale utworzy również zagnieżdżone liczniki, jak opisano powyżej, jeśli licznik o tej nazwie istnieje. Właściwość counter-set
utworzy nowy licznik tylko wtedy, gdy nie ma licznika o tej nazwie. W tym celu użycie dowolnej właściwości działałoby dobrze, jednak counter-set
nie obsługuje tak dobrej przeglądarki, jak counter-reset
, więc obieram praktyczną drogę:
body { counter-reset: heading-counter; }
Teraz, gdy mam licznik, mogę użyć właściwości counter-increment
w selektorze dla nagłówków; powinno to zwiększać licznik za każdym razem, gdy selektor pasuje.
h2 { counter-increment: heading-counter; }
Aby zobaczyć wartość, muszę wyprowadzić ją do dokumentu. Mogę to zrobić, używając Generated Content i dodając ją before
nagłówkiem, jak pokazano w poniższym przykładzie CodePen:
h2::before { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; }
Alternatywnie, mógłbym przekształcić element h2
w element list-item
a następnie użyć ::marker
, jak pokazano poniżej. Jak już szczegółowo opisano, użycie elementu ::marker
ma ograniczoną obsługę przeglądarek. W przeglądarce Firefox powinieneś zobaczyć licznik używany jako znacznik nagłówka, podczas gdy inne przeglądarki pokażą domyślny punktor.
h2 { display: list-item; } h2::marker { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; }
Liczniki na elementach formy
Istnieje również trochę interaktywności, którą można osiągnąć za pomocą liczników CSS — coś, co może wydawać się potrzebne do wykonania JavaScript.
Mam formularz, który zawiera kilka wymaganych pól. Wymagany status można wybrać w CSS za pomocą pseudoklasy :required
, a fakt, że pole nie zostało wypełnione, można wykryć za pomocą pseudoklasy :invalid
. Oznacza to, że możemy sprawdzać pola, które są zarówno wymagane, jak i nieprawidłowe, oraz zwiększać licznik. Następnie wypisz to jako wygenerowaną zawartość.
To, jak przydatne jest to w rzeczywistości, jest dyskusyjne — biorąc pod uwagę, że tak naprawdę nie możemy zrobić nic z tą wartością poza wklejeniem jej do generowanej treści. Istnieją również obawy dotyczące tego, że generowane treści są niedostępne dla niektórych czytników ekranu, dlatego każde użycie, które jest czymś więcej niż tylko dekoracyjnym, wymagałoby zapewnienia innych sposobów dostępu do tych informacji. Przeczytaj „Obsługa ułatwień dostępu dla treści generowanych przez CSS” i nowsze informacje, „Zgodność z czytnikiem ekranu właściwości treści CSS”, aby uzyskać więcej informacji na temat dostępności i generowanej treści.
Pokazuje jednak, że liczniki mogą osiągnąć więcej użytecznych rzeczy niż zwykła numeracja list. Może się zdarzyć, że pewnego dnia ta wiedza przyda się do rozwiązania problemu, nad którym pracujesz.
Dowiedz się więcej
Ten artykuł zakończył się dość daleko od stylizowania list, mimo że wszystko, co opisałem, znajduje się w specyfikacji list CSS. Więcej informacji na temat rzeczy opisanych w poniższych linkach. Jeśli znalazłeś interesujące zastosowanie liczników CSS lub możesz wymyślić rzeczy, do których możesz użyć ::marker
, dodaj uwagę w komentarzach.
-
::marker
-
counter-set
-
counter-reset
-
counter-increment
- „Korzystanie z liczników CSS”, dokumentacja internetowa MDN
- „Liczenie za pomocą liczników CSS i siatki CSS”, CSS-Tricks