Jeśli chodzi o listy, CSS ma całkiem pokaźny zestaw narzędzi do zaoferowania. W HTML dostępne są cztery rodzaje list — listy uporządkowane, listy nieuporządkowane, listy definicji i listy menu. Pod wieloma względami można je formatować, jak zwykły tekst za pomocą technik formatowania tekstu CSS, ale ze względu na ich specyficzną konstrukcję istnieją też specjalne narzędzia CSS służące specjalnie do pracy z listami.
Do podstawowych i najczęściej używanych typów list HTML zaliczają się listy uporządkowane (ol) i listy nieuporządkowane (ul) i to właśnie do nich odnoszą się opisywane na tej stronie techniki. Pozostałe dwa typy list mają trochę inne zastosowanie.
Czym jest element listy
Aby dokładnie zrozumieć wszystkie techniki pracy z listami HTML w CSS, przede wszystkim należy wiedzieć, że w HTML podstawowym elementem listy jest li
, natomiast w CSS elementem listy jest każdy element, który ma własność display
ustawioną na list-item
(elementy li
mają to ustawienie nadane domyślnie).
Oznacza to, że wszystkie ustawienia dotyczące elementów list można zastosować do dowolnego elementu HTML, który został za pomocą CSS zdefiniowany jako element listy, np.:
p {
display: list-item;
}
Ten element akapitu HTML domyślnie w przeglądarce będzie wyglądał tak:
To jest akapit zamieniony w element listy
Cechą wyróżniającą elementy list jest obecność markera, który może być symbolem (w przypadku list nieuporządkowanych) albo liczbą (w przypadku list uporządkowanych). Marker tworzy pola, którego zawartość można formatować za pomocą własności list-style-type
i list-style-image
oraz za pomocą pseudoelementu CSS ::marker. Ponadto do markera odnosi się własność list-style-position
, która określa jego położenie względem treści właściwej elementu listy.
Podsumowując, w CSS dostępne są trzy specjalne własności oraz pseudoelement ::marker
, służące do pracy z markerami elementów list:
list-style-type
— określa typ markera elementu listylist-style-image
— ustawia obraz jako marker listylist-style-position
— określa położenie markera względem treści właściwej elementu listy::marker
— reprezentuje pole tworzone przez marker listy
Istnieje też własność zbiorcza list-style
, która służy do ustawiania powyższych własności w jednej deklaracji.
Metody pracy z tymi podstawowymi własnościami zostały opisane w sekcji Praca z listami w CSS kursu HTML dla początkujących.
Natomiast w dalszej części tego artykułu opisuję zaawansowane techniki pracy z listami, czyli liczniki CSS i tworzenie własnych stylów liczników. Na pierwszy ogień weźmiemy numerację automatyczną za pomocą liczników CSS.
Liczniki i numeracja automatyczna CSS
Liczniki CSS (ang. CSS counters) to specjalny rodzaj konstrukcji służący do automatycznego numerowania dowolnych elementów na stronie, w tym oczywiście elementów list.
Najprostszy licznik pozwala uzyskać dokładnie taki sam efekt, jak domyślne ustawienia listy, ale oprócz tego liczniki dają znacznie szersze możliwości i większą kontrolę nad numerowaniem automatycznym treści.
Dzięki nim można na przykład w łatwy sposób rozpocząć numerowanie od dowolnego numeru, stworzyć numerację wsteczną, zmienić wartość skoku numeracji, czy dodać do niej dowolny przedrostek lub przyrostek.
Poniżej znajduje się wykaz narzędzi niezbędnych do tworzenia i obsługi liczników CSS:
- Własność
counter-reset
— tworzy licznik o określonej nazwie i ewentualnie nadaje mu wartość początkową - Własność
counter-set
— ustawia wartość licznika - Własność
counter-increment
— określa sposób zwiększania wartości licznika - Własność
content
— wstawia treść generowaną - Funkcja
counter()
— wstawia wartość licznika - Funkcja
counters()
— wstawia wartości liczników (używana przy zagnieżdżaniu liczników CSS) - Pseudoelementy
::before
,::after
i::marker
— reprezentują miejsce, w którym własnośćcontent
może wstawić treść generowaną
W pierwszej kolejności należy utworzyć licznik, więc od tego zaczniemy.
Tworzenie i ustawianie wartości początkowej licznika
Do tworzenia liczników służy własność counter-reset
, której wartością powinna być nazwa tworzonego licznika i ewentualnie jego wartość początkowa, np.:
counter-reset: wyliczanka 1;
Ta deklaracja tworzy licznik o nazwie wyliczanka
i wartości początkowej 1
. Gdyby nie została podana wartość początkowa, to przeglądarka zastosowałaby domyślną wartość 0
.
W razie potrzeby w jednej deklaracji można utworzyć kilka liczników, opcjonalnie inicjalizując wszystkie lub tylko wybrane wartością początkową, np.:
counter-reset: wyliczanka 1 moj-licznik strona sekcja naglowek 2;
Ta deklaracja CSS tworzy pięć liczników: wyliczanka
, moj-licznik
, strona
, sekcja
i nagłówek
. Licznik wyliczanka ma wartość początkową 1
, licznik naglowek
ma wartość początkową 2
, a pozostałe mają domyślną wartość początkową 0
.
Ważną kwestią przy tworzeniu licznika jest także wybór elementu, na którym zostanie on zdefiniowany. Powinien on znajdować się na poziomie nadrzędnym względem wszystkich elementów, które będą korzystały ze wspólnej numeracji. Spójrz na poniższy przykładowy fragment dokumentu HTML :
<body>
<div>
<p>Akapit</p>
<p>Akapit</p>
<p>Akapit</p>
</div>
<div>
<p>Akapit</p>
<p>Akapit</p>
<p>Akapit</p>
</div>
</body>
Najpierw licznik zdefiniujemy na elemencie div
:
div {
counter-reset: wyliczanka;
}
W efekcie tego pierwsza grupa elementów p będzie numerowana niezależnie od drugiej, co będzie wyglądało tak:

Jeśli natomiast licznik zdefiniujemy na elemencie body
, to wszystkie akapity zostaną objęte jedną numeracją, ponieważ wszystkie one znajdują się w tym samym elemencie body
.
body {
counter-reset: wyliczanka;
}
Efekt:

Pierwszy krok, czyli utworzenie i inicjalizację licznika, mamy za sobą. Teraz pokażę Ci, jak za jego pomocą ponumerować wybraną grupę elementów.
Wyświetlanie wartości licznika
Do zastosowania numeracji automatycznej do wybranej grupy elementów potrzebne są trzy narzędzia: własność content
, funkcja counter()
oraz jeden z pseudoelementów, np. pseudoelement ::before.
Procedura jest bardzo prosta. Należy utworzyć regułę odnoszącą się do interesujących nas elementów z wybranym pseudoelementem (np. p::before
w poprzednim przykładzie) — pseudoelement tworzy miejsce, w którym można wstawić numerację, własność content
umieszcza ją w tym miejscu, a funkcja counter()
określa nazwę licznika, np.:
body {
counter-reset: wyliczanka;
}
p::before {
content: counter(wyliczanka);
}
Druga reguła powyższego arkusza stylów umieszcza w polu pseudoelementu ::before akapitów numerację licznika o nazwie wyliczanka
, jak widać na poniższym zrzucie ekranu:

Nie da się ukryć, że to jeszcze nie jest efekt, o który nam chodzi. Po pierwsze, wszystkie elementy mają numer 0, a po drugie numer jest złączony z treścią akapitu. Najpierw zajmiemy się tym drugim problemem.
Być może wiesz, że własność content
ma znacznie szersze zastosowanie niż tylko wstawianie wartości liczników do pseudoelementów. W rzeczywistości służy ona do wstawiania tzw. treści generowanej i jako wartość przyjmuje dowolny łańcuch znaków w cudzysłowie. To oznacza, że za funkcją counter()
możemy dodać kropkę i spację (albo jakikolwiek inny tekst), aby odsunąć wartość licznika od treści elementu, np.:
p::before {
content: counter(wyliczanka) ". ";
}
Teraz nasza lista akapitów wygląda tak:

Pozostaje jeszcze tylko zająć się automatyzacją numeracji, bo przecież nie będziemy każdemu elementowi z osobna nadawać numeru za pomocą własności counter-set.
Numeracja rosnąca
Aby wartość licznika rosła dla każdego kolejnego elementu, należy zastosować własność counter-increment
, która przyjmuje nazwę licznika i liczbę całkowitą określającą skok zmiany, tzn. o ile każdy kolejny numer ma być większy od poprzedniego, np.:
p::before {
content: counter(wyliczanka) ". ";
counter-increment: wyliczanka 1;
}
Ta reguła sprawi, że wartość licznika dla każdego kolejnego elementu będzie się zwiększała o jeden. Gdyby zamiast wartości 1
użyto wartości 3
, to numeracja zaczynałaby się od 3 i zwiększałaby się o 3 dla każdego kolejnego elementu.
Numeracja malejąca
Elementy można numerować także odwrotnie, tzn. w kolejności malejącej. Jeśli na przykład mamy sześć akapitów, to zamiast numerować je od 1 do 6, możemy je ponumerować od 6 do 1.
Do tworzenia numeracji malejącej służy funkcja reversed()
przyjmująca jako wartość nazwę licznika i używana jako wartość własności counter-reset
, np.:
body {
counter-reset: reversed(wyliczanka);
}
Ta reguła sprawi, że nasza przykładowa lista akapitów będzie numerowana od końca. Spójrz na poniższy zrzut ekranu:

Zwróć uwagę, że wartości numeracji są ujemne. Aby pozbyć się znaku minusa sprzed numerów, należy własności counter-increment
nadać wartość ujemną, np.:
p::before {
content: counter(wyliczanka) ". ";
counter-increment: wyliczanka -1;
}
Teraz akapity będą numerowane od końca liczbami dodatnimi, jak widać na poniższym rysunku:

Zagnieżdżanie liczników CSS
Oprócz funkcji counter()
istnieje także funkcja counters()
, za pomocą której można w łatwy sposób stworzyć wielopoziomową numerację elementów listy, na przykład taką, jak na poniższym zrzucie ekranu:

Aby utworzyć taką listę bez użycia funkcji counters()
, trzeba by było trochę się nagimnastykować, a i tak rozwiązanie zawsze miałoby jakieś wady, np. konieczność tworzenia klas dla każdego poziomu albo posługiwanie się skomplikowanymi selektorami dziecka i potomka itd.
Dzięki funkcji counters()
listę o takiej strukturze można utworzyć w bardzo prosty sposób. Zwraca ona wartości wszystkich liczników występujące do danego miejsca i tworzy z nich łańcuch wartości połączonych określonym przez użytkownika łańcuchem znaków. Spójrzmy na przykład:
ol {
counter-reset: wyliczanka;
}
li {
counter-increment: wyliczanka;
}
li::marker {
content: counters(wyliczanka, ".");
}
Te reguły zastosujemy do poniższej trzypoziomowej listy HTML:
<ol>
<li>Pierwszy poziom</li>
<li>Pierwszy poziom</i>
<ol>
<li>Drugi poziom</li>
<li>Drugi poziom</li>
<li>Drugi poziom</i>
<ol>
<li>Trzeci poziom</li>
<li>Trzeci poziom</li>
<li>Trzeci poziom</li>
</ol>
</li>
</ol>
</li>
</ol>
Efekt, z dodatkowymi komentarzami wyjaśniającymi, jest pokazany na poniższym zrzucie ekranu.

Jak widać, elementy list zagnieżdżonych są poprawnie ponumerowane. Jest jeszcze tylko jedna rzecz do poprawienia — brakuje spacji lub kropki na końcu ciągów numeracji. Z tym poradzimy sobie przez dodanie kolejnego fragmentu za funkcją counters()
— przypomnę, że wszystko robimy we własności content
, której można przekazać dowolną liczbę łańcuchów znaków.
content: counters(wyliczanka, ".") ". ";
Technikę z użyciem funkcji counters()
można stosować także w połączeniu z innymi elementami HTML, imitując w ten sposób listy, ale jest to niezalecane ze względów związanych z dostępnością — po prostu najlepiej kiedy lista rzeczywiście jest listą.
Tworzenie własnych stylów liczników
W CSS od niedawna (od około 2023 roku) istnieje możliwość tworzenia własnych stylów liczników. Jest to rozszerzenie funkcjonalności własności list-style-type
, która sama daje bardzo szeroki wybór opcji. Jeśli na przykład chcemy stworzyć listę numerowaną w języku mongolskim, to nic prostszego. Wystarczy napisać tak:
list-style-type: mongolian;
Na stronie Własność CSS list-style-type znajduje się wykaz wszystkich wartości tej własności, ale jeśli okaże się on niewystarczający, to możesz stworzyć własny styl za pomocą reguły @counter-style
.
Reguła ta daje bardzo szerokie możliwości i ma parę zaawansowanych ustawień (opisanych na stronie Reguła @counter-style), ale podstawowy sposób posługiwania się nią jest bardzo prosty. Powiedzmy na przykład, że chcemy, aby kolejne punkty naszych list były oznaczane symbolami nożyczek, czaszki, dzwonka i książki, które można znaleźć w zestawie znaków Unicode pod numerami szesnastkowymi odpowiednio 2702, 2620, 1F56D i 1F56E.
Reguła @counter-style
jako wartość przyjmuje tzw. deskryptory, czyli specjalne własności określające różne cechy definiowanego stylu licznika. Dwa najczęściej używane z nich to symbols
i system
. Pierwszy określa listę symboli do oznaczania punktów listy, a drugi — sposób ich stosowania, np. czy mają być stosowane cyklicznie, czy jednorazowo itp. Spójrzmy na konkretny przykład:
@counter-style moj-styl {
symbols: '\2702' '\2620' '\1F56D' '\1F56E';
system: cyclic;
}
W regule tej moj-styl
to nazwa naszego stylu, której będziemy używać we własności list-style-type
. Deskryptor symbols
zawiera zbiór encji CSS reprezentujących kolejno znaki ✂, ☠, 🕭 i 🕮. Natomiast deskryptor system
ma wartość cyclic
oznaczającą, że symbole mają być powtarzane cyklicznie.
Aby zastosować ten styl do listy, wystarczy podać jego nazwę we własności list-style-type
, np.:
ol {
list-style-type: moj-styl;
}
Zastosujemy go do poniższej listy:
<ol>
<li>Raz</li>
<li>Dwa</li>
<li>Trzy</li>
<li>Cztery</li>
<li>Pięć</li>
<li>Sześć</li>
<li>Siedem</li>
<li>Osiem</li>
</ol>
Efekt jest następujący:

Jak widać, symbole są stosowane cyklicznie, ale można to zmienić za pomocą innych wartości deskryptora system. Zachęcam do zapoznania się z opisem wszystkich jego wartości na stronie Reguła @counter-style i do eksperymentowania.