Arkusze stylów w dokumencie HTML mogą pochodzić z kilku źródeł, np. każda przeglądarka internetowa ma własny domyślny zestaw arkuszy stylów, który nadaje elementom podstawowe formatowanie. To właśnie dzięki ustawieniom w tym arkuszu domyślnie odnośniki mają kolor niebieski, a po kliknięciu stają się fioletowe, nagłówki od h1
do h6 mają zróżnicowane rozmiary itd.
Ponadto na stronie internetowej działają też arkusze stylów zdefiniowane przez twórcę tej strony, które „przesłaniają” ustawienia przeglądarki. Na przykład twórca strony może zmienić kolor, rozmiar i krój czcionki wszystkich elementów od h1
do h6, aby nadać im wygląd pasujący do reszty serwisu.
Same arkusze stylów autora strony także mogą pochodzić z kilku źródeł. Mogą być na przykład wpisane bezpośrednio w elementach HTML za pośrednictwem atrybutu style
, jak i znajdować się w zewnętrznym pliku CSS dołączonym do dokumentu za pomocą elementu style
.
Do tego dochodzą jeszcze arkusze stylów użytkownika strony, który również może w niestandardowy sposób zmienić wybrane ustawienia dla własnej wygody. Z tej opcji najczęściej korzystają osoby z wadami wzroku, które chcą ułatwić sobie przeglądanie treści przez ustawienie odpowiedniego kontrastu albo zwiększenie rozmiaru pisma.
Ustawienia CSS z tych wszystkich źródeł (i paru innych) mogą ze sobą kolidować, tzn. w każdym z nich może znajdować się definicja tej samej własności dla tego samego elementu, ale o innej wartości.
Na przykład, mimo że w domyślnym arkuszu stylów przeglądarki odnośniki mają zdefiniowany kolor niebieski, autor strony w swoim arkuszu stylów może zmienić ich kolor na różowy. Wtedy powstaje konflikt, jak w poniższym przykładzie.
Reguła CSS z hipotetycznego arkusza stylów przeglądarki:
Reguła CSS z hipotetycznego arkusza stylów autora strony:
Która reguła w takiej sytuacji zostanie ostatecznie zastosowana i jaki kolor będą miały odnośniki? Odpowiedzi na tego typu pytania można udzielić dzięki znajomości jednego z fundamentalnych mechanizmów Kaskadowych arkuszy stylów – kaskady CSS (ang. cascade).
Kaskada CSS to podstawowy algorytm wyboru deklaracji CSS dla elementów znajdujących się w drzewie dokumentu na podstawie źródła pochodzenia tych deklaracji.
W przytoczonym powyżej przykładzie odnośniki miałyby różowy kolor, ponieważ zgodnie z zasadami kaskady arkusze stylów autora strony są ważniejsze od arkuszy stylów przeglądarki.
W tym rozdziale szczegółowo poznasz zasadę działania kaskady CSS, która jest jednym z dwóch podstawowych mechanizmów decydujących o ostatecznym formatowaniu elementów. Drugim jest dziedziczenie CSS, które zostało opisane w dalszym rozdziale.
Ponieważ kaskada przede wszystkim opisuje relacje pod względem stopnia ważności między arkuszami stylów o różnym pochodzeniu, zaczniemy od przeglądu możliwych źródeł pochodzenia arkuszy stylów, a następnie przyjrzymy się zasadom ich szeregowania zgodnie z tym mechanizmem.
Źródła pochodzenia arkuszy stylów
Arkusze stylów na stronie internetowej mogą pochodzić z trzech podstawowych źródeł oraz z dwóch dodatkowych. Poniżej znajduje się ich zwięzły opis:
- Przeglądarka: wszystkie przeglądarki internetowe zgodne z CSS mają domyślny arkusz stylów, który określa podstawowe formatowanie wszystkich elementów HTML, np. dzięki tym arkuszom standardowe odnośniki do jeszcze nieodwiedzonych stron mają kolor niebieski, odnośniki do odwiedzonych stron są fioletowe itd.
- Użytkownik: czasami użytkownicy używają na wybranych stronach własne arkusze stylów, aby dostosować ich wygląd do swoich potrzeb.
- Autor: twórca strony oczywiście także dołącza do dokumentu własne arkusze stylów, za pomocą których określa wszystkie aspekty jej wyglądu. Arkusze stylów autora także mogą pochodzić z kilku źródeł:
- Arkusze śródliniowe: dodawane bezpośrednio w atrybucie
style
elementów - Arkusze wewnętrzne: dodawane w elemencie
style
w nagłówku dokumentu - Arkusze zewnętrzne: dołączane do dokumentu HTML za pomocą elementu
link
lub dołączane do innych arkuszy stylów za pomocą reguły@import
- Arkusze śródliniowe: dodawane bezpośrednio w atrybucie
Dodatkowe źródła arkuszy stylów, zdefiniowane w rozszerzeniach CSS, to:
- Animacje CSS
- Przejścia CSS
Algorytm kaskady CSS
Kiedy przeglądarka internetowa wczyta dokument HTML i wszystkie dołączone do niego arkusze stylów oraz wygeneruje drzewo dokumentu, rozpoczyna jego analizę w celu określenia ostatecznych ustawień CSS dla wszystkich obecnych elementów.
W tym celu stosuje metodę kaskadową, czyli najpierw wyszukuje wszystkie deklaracje odnoszące się do danego elementu we wszystkich wykrytych źródłach. Jeśli na przykład deklaracja określająca pochylony krój pisma dla elementu em
znajduje się tylko w jednym miejscu, np. w arkuszu stylów przeglądarki, to przeglądarka po prostu ją stosuje i przechodzi do dalszej analizy.
Jeśli jednak podobna deklaracja dotycząca elementu em
znajduje się także w innych arkuszach dołączonych do strony, przeglądarka musi ostatecznie wybrać jedną z nich. Wtedy właśnie stosuje algorytm kaskady, który szereguje źródła arkuszy stylów pod względem stopnia ważności, np. arkusz stylów autora strony jest według zasad kaskady ważniejszy od arkusza stylów przeglądarki, więc w razie konfliktu zostanie zastosowana deklaracja z arkusza autora strony.
Czasami zdarza się też tak, że pochodzenie arkuszy stylów nie rozstrzyga kwestii konfliktu. W takim przypadku włączany jest algorytm obliczania precyzji selektorów, tzn. za ważniejszą jest uznawana ta reguła CSS, która ma precyzyjniejszy selektor. Na przykład selektor section p em
jest precyzyjniejszy (ma większą wagę) niż selektor em
, ponieważ dokładniej określa miejsce elementu w drzewie dokumentu.
Poniżej znajduje się opis algorytmu, według którego przeglądarka wybiera wartości ustawień CSS dla wszystkich elementów w drzewie dokumentu. W punkcie 2 jest opisana kaskada CSS.
- Wyszukiwanie: najpierw przeglądarka wyszukuje we wszystkich dostępnych źródłach wszystkie deklaracje określonej własności CSS odnoszące się do określonego elementu, np. wszystkie deklaracje własności
color
odnoszące się do elementuem
. Program powtarza ten proces dla wszystkich własności odnoszących się do każdego elementu. - Sortowanie wg pochodzenia: następnie przeglądarka sortuje wszystkie znalezione deklaracje według stopnia ważności, o którym decyduje pochodzenie oraz obecność lub brak obecności
słowa kluczowego !important
. Kolejność źródeł od tego, które ma najwyższą rangę, jest następująca:- Deklaracje przejść CSS
- Deklaracje przeglądarki ze słowem kluczowym !
!important
- Deklaracje użytkownika ze słowem kluczowym !
!important
- Deklaracje autora ze słowem kluczowym !
!important
- Deklaracje animacji CSS
- Normalne deklaracje autora
- Normalne deklaracje użytkownika
- Normalne deklaracje przeglądarki
- Sortowanie wg precyzji selektorów: kolidujące ze sobą deklaracje o tej samej wadze pod względem pochodzenia są sortowane według precyzji selektorów (każda deklaracja ma taką samą precyzję selektora, jak reguła, w której się znajduje). Im precyzyjniejszy jest selektor, tym większa jest jego waga. Pseudoelementy liczą się jako zwykłe elementy, a pseudoklasy liczą się jako zwykłe klasy. Natomiast atrybut
style
nie reprezentuje selektora, ale mimo to reprezentuje najwyższą wagę. - Filtrowanie wg kolejności: Jeśli żaden z powyższych zabiegów nie pozwolił ostatecznie wybrać jednej deklaracji, decyduje kolejność, tzn. zastosowana zostaje ta deklaracja, która została zdefiniowana najpóźniej, przy czym:
- Deklaracje zaimportowane do arkusza stylów za pomocą reguły
@import
są traktowane tak, jakby znajdowały się w miejscu występowania tej reguły. - Deklaracje pochodzące z zewnętrznych arkuszy stylów dołączonych do dokumentu za pomocą elementu
style
są traktowane tak, jakby znajdowały się w miejscu występowania tego elementu.
- Deklaracje zaimportowane do arkusza stylów za pomocą reguły
W drugim punkcie powyższej listy jest mowa o słowie kluczowym !important
, a w trzecim – o precyzji selektorów. Przyjrzymy się tym zagadnieniom dokładniej.
Słowo kluczowe !important
Na wstępie należy zaznaczyć, że ściśle rzecz biorąc !important
nie jest słowem kluczowym, tylko połączeniem znaku sygnalizującego !
ze słowem kluczowym important
, ale chyba możemy pozwolić sobie na drobne uproszczenie i całość nazywać po prostu słowem kluczowym.
Dodanie do deklaracji słowa kluczowego !important
, np. a {color: black !important}
, powoduje podniesienie jej rangi w sposób opisany w punkcie 2 opisu algorytmu wybierania deklaracji CSS dla elementów.
Na przykład dodatek tego słowa do deklaracji w arkuszu stylów użytkownika sprawia, że dana deklaracja staje się „ważniejsza” od analogicznej deklaracji zdefiniowanej w arkuszu stylów autora strony bez względu na inne czynniki, takie jak np. precyzja selektorów. Spójrz na poniższy przykład.
Arkusz stylów autora:
Arkusz stylów użytkownika:
W tym przypadku odnośniki będą miały kolor czerwony, mimo że w normalnej sytuacji arkusze stylów autora są ważniejsze, a ponadto reguła w arkuszu stylów autora ma precyzyjniejszy selektor.
Precyzja selektorów
W trzecim punkcie opisu algorytmu wyboru wartości CSS dla elementów przez przeglądarkę dowiedzieliśmy się, że jeśli wcześniejsze metody zawiodą, o wyborze deklaracji decyduje precyzja selektora reguły, w której się ona znajduje. Algorytm obliczania precyzji selektorów jest ściśle określony.
Precyzję selektora CSS określa wartość składająca się z następujących czterech członów ustawionych w takiej kolejności, w jakiej są wymienione na poniższej liście:
- Jeśli deklaracja pochodzi z atrybutu
style
elementu, to pierwszy człon (a) ma wartość 1. W przeciwnym przypadku jego wartość wynosi 0. - Drugi człon (b) to liczba selektorów identyfikatora. Należy pamiętać, że ta zasada dotyczy właśnie selektora identyfikatora, a nie selektora atrybutu, tzn.
[id=identyifkator]
liczy się jako zwykły atrybut (c), a#identyfikator
– jako identyfikator (b). - Trzeci człon (c) to liczba selektorów atrybutu, klasy i pseudoklasy
- Czwarty człon (d) to liczba selektorów typu (nazw elementów) i selektorów pseudoelementu.
Połączenie tych czterech liczb daje wartość określającą precyzję selektora. Im wyższa jest ta wartość, tym większa jest precyzja selektora. Poniższa tabela zawiera kilka przykładowych selektorów z opisem ich precyzji.
Selektor | Precyzja | Opis |
---|---|---|
a | 0001 | a=0, b=0, c=0, d=1 – tylko jedna nazwa elementu |
div a | 0002 | a=0, b=0, c=0, d=2 – dwie nazwy elementów |
.header a | 0011 | a=0, b=0, c=1, d=1 – jedna nazwa elementu i jedna klasa |
.header a[href] | 0021 | a=0, b=0, c=2, d=1 – atrybut i klasa dają 2 na trzeciej pozycji, a nazwa elementu daje 1 na czwartej pozycji |
#header a | 0101 | a=0, b=0, c=2, d=1 – jeden identyfikator i jedna nazwa elementu |
#header #header | 0200 | a=0, b=2, c=0, d=0 – dwa identyfikatory. Selektory składowe można powtarzać, aby podnieść precyzję całego selektora, choć nie należy to do dobrych praktyk |
* | 0000 | Selektor uniwersalny ma precyzję zerową |
style="" | 1000 | Ten przypadek jest szczególny, ponieważ atrybut style nie jest selektorem i nie może zawierać selektorów. W związku z tym określono, że deklaracje z atrybutu style mają największą wagę: a=1, b=2, c=0, d=0 |
Kaskada CSS to podstawowa metoda nadawania elementom wartości ustawień CSS polegająca na ich szeregowaniu wg źródła pochodzenia. Drugim ważnym mechanizmem nabywania przez elementy wartości ustawień CSS jest dziedziczenie, którego opis znajduje się w następnym rozdziale.