Selektory#

Pseudoklasy#

Koncepcję pseudoklasy # (pseudo-class) wprowadzono, aby umożliwić wybór elementów na podstawie informacji, która znajduje się poza drzewa dokumentu lub która może być niewygodna lub niemożliwa do wyrażenia za pomocą innych selektorów prostych.

Pseudoklasa zawsze składa się ze znaku dwukropka (U+003A, :), po którym następuje nazwa pseudoklasy. Pewną odmianą pseudoklasy będzie pseudoklasa funkcyjna # (functional pseudo-class), gdzie po jej nazwie umieszcza się jeden lub większą liczbę argumentów otoczonych nawiasami (podobnie jak w przypadku funkcji CSS lub JS). Białe znaki są opcjonalne między nawiasami i argumentami, ale nie między nazwą pseudoklasy a nawiasami. Jeśli argumenty są rozdzielone przecinkami, to białe znaki są opcjonalne przed/po każdym przecinku.

Poniższe selektory pseudoklas są prawidłowe:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
:target
:visited

:not(p)
:not(p,div)
:not( p , div )

Pseudoklasy są dozwolone we wszystkich selektorach złożonych zawartych w selektorze. Mogą pojawiać się w dowolnym miejscu selektora złożonego, zaraz za rozpoczynającym selektorem typu lub (z ewentualnie pominiętym) selektorem uniwersalnym. Nazwy pseudoklas są nieczułe na wielkość liter ASCII. Niektóre pseudoklasy są wzajemnie wykluczające (tzn. zawierający je selektor złożony będzie poprawny, ale nigdy niczego nie dopasuje), podczas gdy inne mogą mieć jednoczesne zastosowanie do tego samego elementu.

Pseudoklasy mogą być dynamiczne w tym sensie, że element może nabyć lub utracić pseudoklasę w zależności od oddziaływania użytkownika na dokument. Dynamiczna pseudoklasa klasyfikuje elementy na podstawie innych kryteriów niż ich nazwy, atrybuty lub zawartość, raczej pod uwagę brane są cechy, których nie można wydedukować bazując na drzewie dokumentu. Pseudoklasy nie pojawiają się i nie modyfikują źródłowego dokumentu lub drzewa dokumentu.

Specyfikacja selektorów charakteryzuje pseudoklasy bardzo ogólnikowo, tak aby całość mogła mieć zastosowanie w dowolnym języku dokumentu. Pozostałe specyfikacje mogą zawężać/precyzować obszar stosowania każdej z tych pseudoklas. Tak dzieje się chociażby w przypadku najnowszego HTML5, gdzie utworzono specjalną sekcję z wytycznymi dla stosowania pseudoklas CSS. Chcąc zachować przejrzysty opis selektorów materiał związany wyłącznie z HTML-em prawdopodobnie przeniosę do osobnej podstrony (w niedalekiej przyszłości).

W zależności od spełnianych funkcji wszystkie pseudoklasy można podzielić na kilka podstawowych kategorii. Poniżej znajduje się krótka charakterystyka każdej z nich.

Pseudoklasy kombinacji logicznych#

Ten rodzaj pseudoklas pozwala wprowadzić "namiastkę logiki" przy tworzeniu selektorów. Istnieją tylko dwie pseudoklasy tej kategorii:

Pseudoklasy lingwistyczne#

Ten rodzaj pseudoklas pozwala dopasować elementy w zależności od ich cech lingwistycznych, np. kierunku tekstu czy ustawionego języka. Istnieją tylko dwie pseudoklasy tej kategorii:

Pseudoklasy lokalizacji#

W językach znacznikowych pojawia się pojęcie hiperłącza # (hyperlink), które odnosi się do elementów z jawnie zadeklarowanym atrybutem href. W HTML-u hiperłączami mogą być elementy <a>, <area> lub <link>.

Wyjątkiem będzie element <base>, który pomimo dozwolonego atrybut href, nie stanowi hiperłącza, i w kontekście selektorów jest pomijany we wszystkich specyfikacjach.

HTML5 wprowadza szczegółowy podział dla elementów potocznie nazywanych linkami. Od tej pory wyróżnia się linki do zasobów zewnętrznych oraz hiperłącza. Nie powinno to jednak zaburzać pierwotnej (wciąż prawidłowej) koncepcji, którą przyjąłem w opisie pseudoklas.

Pseudoklasy lokalizacji (pięć pierwszych) pozwalają dopasować hiperłącza w zależności od ich specyficznych cech, np. historii odwiedzin lub pochodzenia. Sumarycznie istnieje siedem pseudoklasy tej kategorii:

Z praktycznego punktu widzenia jedynie odsyłacze, czyli elementy <a>, będą rozpatrywane w pseudoklasach tej kategorii. Dzieje się tak dlatego, że tylko odsyłacze mogą zawierać treść między znacznikiem otwierającym i znacznikiem zamykającym, która będzie podlegała stylizacji. Pozostałe elementy z dozwolonym atrybutem href są elementami pustymi, dlatego też nie zawierają żadnej treści, dla której style CSS byłyby aplikowane. Umieszczenie czegokolwiek wewnątrz elementów pustych jest traktowane jak błąd, który zostanie skorygowany przez parser HTML. Również deklaracja atrybutu href w elementach, które na to nie zezwalają, stanowi błąd i nie wpływa na działanie selektorów.

Przy deklarowaniu pseudoklas lokalizacji, zgodnie z powyższymi uwagami, można po prostu pominąć selektor typu, czyli zamiast a:link wystarczy samo :link. Tylko w odsyłaczach zaobserwujemy jakiekolwiek efekty wizualne, zatem cały selektor można w ten sposób uprościć.

Prosty przykład (z błędami):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!DOCTYPE html>
<html>

<head>

	<style>

		a {font-weight: bold;}
		:link {color: red;}

	</style>

</head>

<body>

	<p>Akapit z <a href="www.example.com">odsyłaczem w kolorze czerwonym</a>.</p>
	<p>Akapit z <a>odsyłaczem bez atrybutu HREF</a>.</p>

	<p href="www.example.com">Akapit z niedozwolonym atrybutem (href="www.example.com").</p>

	<area href="www.example.com">Niedozwolona zawartość w elemencie AREA.</area>

</body>

</html>

W przypadku języka HTML powyższy przykład tak czy inaczej będzie działał, ze względu na obsługę błędów, ale parser XML przerwie pracę w chwili wystąpienia pierwszej pomyłki.

Pseudoklasy akcji użytkownika#

Interaktywne aplikacje klienckie czasami zmieniają sposób renderowania strony w odpowiedzi na działania użytkownika. Pseudoklasy akcji użytkownika pozwalają dopasować elementy, na których akcja jest wykonywana. W przypadku aplikacji klienckich pozbawionych interaktywności, pseudoklasy te są poprawne, ale nie dopasowują żadnego elementu. Istnieje pięć pseudoklas tej kategorii:

Pseudoklasy akcji użytkownika nie wykluczają się wzajemnie. Element może pasować do wielu pseudoklas w tym samym czasie.

Pseudoklasy wejścia#

Wejście # (input) to element, który pozwala użytkownikowi wprowadzić jakieś dane wejściowe (input value). W HTML-u takim sztandarowym przykładem wejścia jest kontrolka formularza o identycznej nazwie, czyli element input, no ale istnieją też inne.

Pseudoklasy wejścia pozwalają dopasować wejściowe elementy pod kątem specyficznych cech. Z tego względu dzieli się je na kolejne kategorie.

Stany kontroli wejścia#

Stany wartości wejścia#

Sprawdzenie wartości wejścia#

Pseudoklasy struktury drzewa#

Selektory wprowadzają pojęcie pseudoklas strukturalnych (structural pseudo-classes), aby umożliwić wybór elementów na podstawie dodatkowy informacji pochodzących wprost z drzewa dokumentu, i które nie mogłyby zostać wybrane za pomocą innych selektorów prostych lub kombinatorów.

Samodzielny tekst (czyli węzły tekstowe) lub inne węzły niebędące elementami są pomijane przy wyliczaniu pozycji elementu w liście dzieci jego rodzica. Przy obliczaniu pozycji elementu w liście dzieci jego rodzica numeracja zaczyna się od 1.

Indeksowanie elementów w przypadku CSS przebiega inaczej, niż w przypadku klasycznych języków programowania (np. JavaScript), gdzie numeracja rozpoczyna się od 0 (szczegóły).

Pseudoklasy struktury drzewa dzieli się na kolejne kategorie. W przypadku pseudoklas indeksowania należy zapoznać się z mikroskładnią An+B. Na pierwszy rzut oka całość może odstraszać, dlatego też umieszczę (w razie konieczności) dokładniejsze opisy dla każdej kategorii.

Pseudoklasy podstawowej struktury#

Pseudoklasy indeksowania dzieci#

Pseudoklasy indeksowania dzieci tego samego typu#

Ten rodzaj pseudoklas warto omówić nieco dokładniej. One również dotyczą dzieci pewnego elementu, ale lista dzieci jest dzielona na kolejne listy, do której trafiają elementy tego samego typu (czyli z tą samą nazwą tagu). Z technicznego punktu widzenia typ elementu reprezentuje nazwę rozszerzoną, zatem uwzględniane będą przestrzenie nazw.

Dopiero w tych cząstkowych listach z dziećmi o identycznym typie następuje indeksowanie i wybór konkretnych elementów. Efektem tego jest to, że np. termin pierwsze dziecko (tego samego typu) będzie odnosił się do cząstkowej listy, a nie do listy wszystkich dzieci; czyli akapit, który występuje po elemencie hr, gdzie obydwa elementy są dziećmi div, jest traktowany w kontekście pierwszego dziecka tego samego typu, ale nie w ogólnym ujęciu pierwszego dziecka swojego rodzica (za ten stan odpowiadają wcześniejsze pseudoklasy).

Poniższe dwie struktury znacznikowe powinny rozjaśnić sprawę:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!-- Indeksowanie dzieci tego samego typu -->
<div>							<!-- Rodzic -->

	<hr>						<!-- Indeks 1 (pierwsze dziecko typu HR) -->
	<p>Pierwszy akapit.</p>		<!-- Indeks 1 (pierwsze dziecko typu P) -->
	<p>Drugi akapit.</p>		<!-- Indeks 2 (drugie dziecko typu P) -->
	<p>Trzeci akapit.</p>		<!-- Indeks 3 (trzecie dziecko typu P) -->

</div>

<!-- Indeksowanie dzieci niezależnie od typu -->
<div>							<!-- Rodzic -->

	<hr>						<!-- Indeks 1 (pierwsze dziecko rodzica) -->
	<p>Pierwszy akapit.</p>		<!-- Indeks 2 (drugie dziecko rodzica) -->
	<p>Drugi akapit.</p>		<!-- Indeks 3 (trzecie dziecko rodzica) -->
	<p>Czwarty akapit.</p>		<!-- Indeks 4 (czwarte dziecko rodzica) -->

</div>

Słowo "child" usunięto z nazw pseudoklas w celu skrócenia ich zapisu, w zamian dodano jedynie "of-type". Pomimo tego wciąż poruszamy się w obrębie dzieci jakiegoś elementu, o czym nie należy zapominać przy stosowaniu pseudoklas indeksowania.

Pseudoklasy indeksowania dzieci wybranego typu#

Kolejna grupa indeksujących pseudoklas wymagająca krótkiego omówienia. Tym się różni od poprzednich wariantów, że indeksowanie odbywa się na zbiorze elementów (też rodzeństwie), które pasują do przekazanego selektora.

Różnica jest istotna, choć na pierwszy rzut oka można jej nie zauważyć. Załóżmy, że rozpatrujemy selektor p.foo:nth-child(even), co w rzeczywistości oznacza: "ze wszystkich elementów będących rodzeństwem wybierz te parzyste, pozostaw tylko elementy <p>, i na koniec wybierz jedynie te z klasą foo. Nie należy tego mylić z interpretacją: "spośród elementów <p> z klasą foo wybierz tylko te parzyste". Pseudoklasy :nth-match() i :nth-last-match() pozwalają budować selektory zgodne z drugą interpretacją.

Podobnie jest z pseudoklasami indeksowania dzieci tego samego typu, w niektórych przypadkach prostsze selektory działają identycznie, np. dla zapisu p:nth-of-type(even) i :nth-match(even of p) efekt będzie taki sam, ale w sytuacji p.foo:nth-of-type(even) i :nth-match(even of p.foo) wymienności nie ma. W drugim selektorze indeksowane są jedynie elementy <p> mające klasę foo, gdzie w pierwszym selektorze indeksowanie dotyczy wszystkich akapitów (będących elementami tego samego typu).

Poniższa struktura znacznikowa powinna rozjaśnić sprawę:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!-- Indeksowanie dzieci wybranego typu -->
<div>									<!-- Rodzic -->

	<p class="foo">Pierwszy akapit.</p>	<!-- Indeks 1 (pierwsze dziecko typu P.foo) -->
	<p class="foo">Drugi akapit.</p>	<!-- Indeks 2 (drugie dziecko typu P.foo) -->
	<p>Trzeci akapit.</p>
	<p class="foo">Czwarty akapit.</p>	<!-- Indeks 3 (trzecie dziecko typu P.foo) -->
	<p>Piąty akapit.</p>

</div>

Dodatkowym plusem nowych pseudoklas jest to, że przyjmują one listę selektorów w argumencie, przez co zapis wielu selektorów (dla tych samych deklaracji) można uprościć do jednego polecenia.

Na chwilę obecną żadna aktualna przeglądarka nie obsługuje nowych pseudoklas. Opis zweryfikuję w niedalekiej przyszłości, kiedy będzie można przeprowadzić jakieś testy.

Pseudoklasy indeksowania kolumn#

Jest jeszcze jedna specyficzna grupa pseudoklas, która wraz z kombinatorem kolumny, umieszczona została w osobnym dziale zatytułowanym "Grid-Structural Selectors", zatem dotyczy tzw. selektorów struktury siatki. Ze względu na indeksujący charakter pseudoklas postanowiłem scharakteryzować zagadnienie właśnie w tym miejscu.

Podwójny związek komórki # (cell) w dwuwymiarowej siatce (2D grid), czyli do jej wiersza (row) i kolumny # (column), nie może być jednocześnie wyrażany za pomocą rodzicielstwa w hierarchicznym języku znaczników. Tylko jeden z tych związków może być reprezentowany hierarchicznie: inne muszą być bezpośrednio lub pośrednio definiowane w semantyce języków dokumentów.

W językach HTML i DocBock, dwóch najbardziej popularnych hierarchicznych języków znaczników, priorytetem w strukturze są wiersze (czyli, że powiązania wierszy są reprezentowane hierarchicznie na zasadzie zagnieżdżenia); kolumny muszą być dorozumiane # (deklarowane pośrednio). W tabelach HTML kolumny (i ich grupy) wydzielamy za pomocą odpowiednio wprowadzonych elementów <col> i <colgroup>.

Celem nowych selektorów struktury siatki jest zatem możliwość reprezentowania tych właśnie pośrednich relacji kolumn. Dzięki dedykowanym pseudoklasom dla kolumn możemy wybierać kolejne kolumny (i w konsekwencji wszystkie jej komórki) w oparciu o zdefiniowany krok, na podobnej zasadzie, jak w pozostałych (opisanych do tej pory) pseudoklasach indeksowania. Różnica jest taka, że w tym przypadku indeksowaniu podlegają kolumny z pewnej grupy kolumn (każda grupa kolumn jest traktowana niezależnie), co w rzeczywistości oznacza wybranie wszystkich komórek z każdej kolejnej kolumny w danej grupie kolumn.

Poniższa struktura znacznikowa dwuwymiarowej siatki (tabeli HTML) powinna rozjaśnić sprawę:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!-- Indeksowanie kolumn -->
<table border="1">

	<colgroup span="2"></colgroup>	<!-- Wybieramy dwie pierwsze kolumny (A, B) -->
	<colgroup>
		<col span="1">		<!-- Wybieramy trzecią kolumnę (C) -->
		<col span="4">		<!-- Wybieramy cztery kolejne kolumny (D, E, F, G) -->
	</colgroup>

	<tr>
		<td>A1</td>		<!-- Indeks 1 (Komórka z colgroup span="2") -->
		<td>B1</td>		<!-- Indeks 2 (Komórka z colgroup span="2") -->
		<td>C1</td>		<!-- Indeks 1 (Komórka z col span="1") -->
		<td>D1</td>		<!-- Indeks 1 (Komórka z col span="4") -->
		<td>E1</td>		<!-- Indeks 2 (Komórka z col span="4") -->
		<td>F1</td>		<!-- Indeks 3 (Komórka z col span="4") -->
		<td>G1</td>		<!-- Indeks 4 (Komórka z col span="4") -->
	</tr>

	<tr>
		<td>A2</td>		<!-- Indeks 1 (Komórka z colgroup span="2") -->
		<td>B2</td>		<!-- Indeks 2 (Komórka z colgroup span="2") -->
		<td>C2</td>		<!-- Indeks 1 (Komórka z col span="1") -->
		<td>D2</td>		<!-- Indeks 1 (Komórka z col span="4") -->
		<td>E2</td>		<!-- Indeks 2 (Komórka z col span="4") -->
		<td>F2</td>		<!-- Indeks 3 (Komórka z col span="4") -->
		<td>G2</td>		<!-- Indeks 4 (Komórka z col span="4") -->
	</tr>

</table>

W strukturach z priorytetem kolumnowym selektory wyrażają pośrednią relację wierszy.

Pseudoklasy indeksowania: mikroskładnia An+B#

W kilku pseudoklasach struktury drzewa, zwanych też pseudoklasami indeksowania, wybór elementów może przebiegać w sposób cykliczny (szczególnie w przypadku pseudoklas funkcyjnych), gdzie decydujące znaczenie ma indeks elementu w liście elementów spełniających relację rodzeństwa. Funkcyjne pseudoklasy indeksowania przyjmują argument, który pozwala w cykliczny sposób opisać indeks takiego elementu, tzn. że rzeczywista wartość będzie ulegała zmianie i wybierane będą elementy zachowujące pewien "odstęp" od siebie (np. co drugi, trzeci czy piąty). Argument ten powinien spełniać notację An+B.

Zanim przejdziemy do konkretów warto omówić sposób indeksowania elementów # w zależności od danego języka. W większości przypadków indeksowanie zaczyna się od 0, czyli element pierwszy ma indeks 0, elementu drugi ma indeks 1, element trzeci ma indeks 2 itd. W przypadku CSS (i w konsekwencji selektorów) indeksowanie zaczyna się od 1. Warto o tym pamiętać, szczególnie kiedy ktoś dynamicznie manipuluje strukturą i wyglądem strony.

W przypadku pseudoklas CSS istotna jest także kolejność indeksowania.

Rozważmy następującą strukturę znacznikową:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<ul>
		<li>Pierwszy element listy</li>
		<li>Drugi element listy</li>
		<li>Trzeci element listy</li>
		<li>Czwarty element listy</li>
		<li>Piąty element listy</li>
		<li>itd.</li>
</ul>

Wszystkich elementów li wewnątrz ul jest sześć, ale w zależności od stosowanej technologii mają one różne indeksy:

Zawartość liIndeks DOMIndeks CSS
Pierwszy element listy01
Drugi element listy12
Trzeci element listy23
Czwarty element listy34
Piąty element listy45
itd.56

Wyliczoną wartość w notacji An+B porównujemy względem indeksu CSS. Jeśli chcemy szybko przejść z indeksu CSS do indeksu DOM wystarczy odjąć jedynkę, co jest równoważne zapisowi An+B - 1 i często pojawia się w samej specyfikacji selektorów.

Kolejna sprawa to sposób w jaki próbuje się wyjaśniać działanie pseudoklas idneksowania. Istnieją dwa równorzędne podejścia. Załóżmy, że mamy do czynienia z następującą pseudoklasą:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
:nth-child(n)

Można ją opisać następująco

Obydwie formy są prawidłowe, pierwsza zazwyczaj pojawia się przy opisach działania pseudoklas, druga wynika bezpośrednio z ich nazw. Ogólnie ujmując chodzi o to, że element może zawierać inne elementy, a te które znajdują się o jeden poziom niżej w drzewie węzłów są jego dziećmi. Element posiada zatem indeksowaną listę swoich dzieci (która może być pusta). Z racji tego, że wszystkie dzieci są dla siebie rodzeństwem, to w odniesieniu do dzieci lista ta może być nazwana listą rodzeństwa i elementy tej listy mogą być rozważane w kontekście rodzeństwa (analogiczne zwroty to brat|siostra|sąsiad|rówieśnik).

Obracanie się wyłącznie w obrębie terminu "dziecko" jest łatwiejsze do zrozumienia (nawet dla mnie). Przy opisach poszczególnych pseudoklas będę starał się unikać innych zwrotów nawiązujących do rodzeństwa.

Niezależnie od tego, jaka tajemna wiedza pojawi się dalej, trzeba zatem zapamiętać, że pseudoklasy indeksujące dotyczą jedynie dzieci (elementów) w innych elementach. Oczywiście całość można zawężać do dzieci konkretnego typu, do dzieci konkretnego typu w konkretnym elemencie, lub innej formy selektora:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
p:nth-child(n)
p > :nth-child(n)

Dla ułatwienia warto odczytywać selektory w kierunku prawo-lewo, dzięki czemu unikniemy potencjalnych pomyłek. Prawdę mówiąc rzeczywista obsługa selektorów tak właśnie wygląda. Podsumowując tę część, zapis p:nth-child(n) ma zastosowanie do wszystkich elementów p, które są dziećmi w dowolnych elementach. Nie należy tego mylić z wyborem dzieci w elementach p, co odzwierciedla drugi selektor p > :nth-child(n).

Lista dzieci jednego elementu jest niezależna od listy dzieci innego elementu. Obliczanie notacji An+B i wybieranie konkretnego dziecka w danej liście musi być przeprowadzane osobno dla każdego rodzica, który tworzy swoją listę dzieci. W niektórych przypadkach może wyglądać to tak, jakbyśmy do jednego kotła wrzucili wszystkie dzieci ze wszystkich elementów, a dopiero potem dokonywali wyboru, ale będą to sporadyczne wyjątki nie stanowiące reguły.

Dopiero teraz możemy omówić składnię argumentu w pseudoklasach indeksowania. Ogólnie rzecz biorąc argument ma postać tzw. notacji, którą wyrażamy następująco:

Notacja An+B
  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
An+B

gdzie poszczególne człony oznaczają

Osoby po kierunkach technicznych powinny zauważyć podobieństwo do funkcji liniowej, którą wyraża się wzorem f(x)=Ax+B. Wykresem funkcji liniowej jest prosta y=Ax+B. W przypadku notacji CSS mamy po prostu zawężone dopuszczalne wartości dla A, x (czyli n) i B.

Wracam do dawnych szkolnych czasów nie bez powodu. Warto podkreślić znaczenie stałej A, którą po fachowemu nazywa się współczynnikiem kierunkowym prostej # i której wartość determinuje charakter funkcji:

Po utworzeniu odpowiedniego wzoru wystarczy go wpisać między nawiasami funkcyjnej pseudoklasy. Oto kilka prawidłowych selektorów (więcej szczegółów):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
:nth-child(4)
:nth-child(n)
:nth-child(2n+4)
:nth-child(-2n-4)

Notacja An+B wskazuje na kolejne elementy pewnej listy, podstawiając kolejno (w odniesieniu do naszych dywagacji jest to proces teoretyczny) pod n każdą dodatnią liczbę całkowitą zaczynając od zero, gdzie pierwszy element takiej listy oznaczany jest indeksem 1 (nie 0, jak wyjaśniłem wcześniej).

Nie mam żadnych konkretnych informacji w jaki sposób przeglądarki internetowe określają graniczną wartość dla n. Proces ten powinien być zależny od liczby elementów w liście oraz zadeklarowanych wartości dla A i B.

Dla wartości A i B większych od zera notacja ma taki efekty, jak gdyby lista podzielona została na grupy, w każdej z nich znalazło się elementów w ilości A (ostatnia grupa rozpatrywana jest w kategoriach reszty), i w ostateczności wybrane zostały elementy z indeksem B w każdej z tych grupy.

Wartości A i B mogą być ujemne, ale w praktyce jedynie dodatnie wyliczenie An+B (przy n ≥ 0) jest stosowane.

Jeśli zarówno A jak i B jest zerem, to pseudoklasa nie reprezentuje żadnego elementu w liście.

Notację An+B można zapisać w formie pojedynczego słowa kluczowego. Dozwolone są jedynie dwie takie wartości:

W ramach ćwiczenia przeanalizujmy dokładniej notację elementów nieparzystych:

nWzór (2n+1)Wynik (indeks CSS)
02*0+11
12*1+13
22*2+15
32*3+17
42*4+19
itd.itd.itd.

W podobny sposób można tworzyć i analizować dowolne warianty An+B. Dla osób bez obycia matematycznego (choć są to podstawy z podstaw) istnieje jeszcze jeden prosty sposób wyjaśniający omawianą notacje:

Warto na chwilę zatrzymać się przy stałej B. Możliwe jest podanie takiej wartości, która nie wskazuje na żaden rzeczywisty element. Dotyczy to każdej ujemnej wartości (bo indeksy w listach elementów zaczynają się od 1), ale nie należy zapominać również o dodatnich wartościach, które mogą być większe od największego indeksu w liście elementów. Wymienione przypadki nie są błędne, tak czy inaczej możliwe będzie wybranie rzeczywistego elementu (w zależność od znaku przy A), bo z każdym kolejnym cyklem wyliczona wartość może zmierzać w kierunku osiągnięcia rzeczywistych elementów.

Każdy powinien wybrać najodpowiedniejszy dla siebie sposób interpretacji notacji An+B.

Specyficzne przypadki#

Dokładna gramatyka dla notacji An+B, którą wyraża typ <an+b>, znajduje się w module "CSS Syntax Module Level 3". Z praktycznego punktu widzenia wystarczy scharakteryzować jej najważniejsze kwestie.

Notacja An+B to w zasadzie wyrażenie matematyczne, zatem, w zależności od wartości A i B, może przyjmować różne formy.

Gdy A=0 to część An można pominąć (o ile część B nie została pominięta). Gdy An nie występuje i B jest nieujemne, to znak + przed B (gdy jest dozwolony) również można pominąć. W tym przypadku upraszcza jedynie składnię do samego B:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
0n+5	/* reprezentuje piąty element listy */
+5	/* to samo co 0n+5 */
5	/* to samo co 0n+5 */

Dla A=-1 lub A=1 cyfrę przed n można pominąć:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
1n+0	/* reprezentuje wszystkie elementy listy */
n+0	/* to samo co 1n+0 */
n	/* to samo co 1n+0 */

Oznaczenie dodatnich wartości A znakiem + nie jest konieczne (choć prawidłowe):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
+5n	/* reprezentuje co piąty element listy */
5n	/* to samo co +5n */

Jeśli B=0 to każdy kolejny element (z krokiem A) jest wybierany. W tym przypadku część +B (lub -B) można pominąć (o ile część A nie została pominięta):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
2n+0	/* reprezentuje co drugi element listy */
2n-0	/* to samo co 2n+0 */
2n	/* to samo co 2n+0 */

Trzeba pamiętać też o tym, że wartości B nie można oznaczać ujemnym znakiem -; w takim przypadku należy zamienić w notacji działanie sumy (znak +) na różnicę (znak -):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
2n - 1	/* poprawny zapis */
  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
2n + -1	/*  błędny zapis */

Białe znaki są dozwolone po nawiasie otwierającym ( i nawiasie zamykającym ) pseudoklasę, jak również po obu stronach sumy (+) lub różnicy (-), które oddzielają od siebie części An i B (w przypadku obecności tych części):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
:nth-child( 3n + 1 )
:nth-child( +3n - 2 )
:nth-child( -n+ 6)
:nth-child( +6 )

Nie mogą jednak rozdzielać symboli oznaczających znak w A lub B oraz symboli poprzedzających n:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
:nth-child(3 n)
:nth-child(+ 2n)
:nth-child(+ 2)
Kolejność indeksowania#

Pseudoklasy indeksujące zazwyczaj występują w dwóch wariantach, jak chociażby w przypadku nth-child() i nth-last-child(). Różnica między nimi polega na odmiennym sposobie indeksowania elementów w liście, zależnie od ich kolejności, dlatego też wyróżniamy:

Obliczanie cyklicznej wartości w notacji An+B jest identyczne, ale wybieranie elementów w oparciu o jej rezultat zależy także od wyboru konkretnej pseudoklasy (z normalną czy odwrotną kolejnością indeksowania).

Przypominam tylko, że w zależność od znaku przy A oraz początku wskazywanym przez B możemy poruszać się zgodnie lub przeciwnie względem sposobu indeksowania elementów danej pseudoklasy. Zgodny kierunek jest bardziej uniwersalny bo nie jest podatny na dynamiczne dodawanie kolejnych elementów (w dowolnej ilość), w przypadku wstecznego kierunku musimy dobrać odpowiednio dużą wartość dla B.

Przy założeniu, że znamy maksymalną liczbę dzieci w elementach (i nie będzie ona ulegała zmianie), możemy bez problemu osiągnąć identyczne efekty stosując obydwa rodzaje pseudoklas.

Pasek społecznościowy

SPIS TREŚCI AKTUALNEJ STRONY

Selektory (H1) Pseudoklasy (H2) Pseudoklasy kombinacji logicznych (H3) Pseudoklasy lingwistyczne (H3) Pseudoklasy lokalizacji (H3) Pseudoklasy akcji użytkownika (H3) Pseudoklasy wejścia (H3) Stany kontroli wejścia (H4) Stany wartości wejścia (H4) Sprawdzenie wartości wejścia (H4) Pseudoklasy struktury drzewa (H3) Pseudoklasy podstawowej struktury (H4) Pseudoklasy indeksowania dzieci (H4) Pseudoklasy indeksowania dzieci tego samego typu (H4) Pseudoklasy indeksowania dzieci wybranego typu (H4) Pseudoklasy indeksowania kolumn (H4) Pseudoklasy indeksowania: mikroskładnia An+B (H4) Notacja An+B (H5) Specyficzne przypadki (H5) Kolejność indeksowania (H5)