Podstawy#
Kaskadowość i dziedziczenie#
Reguły stylów mogą pochodzić z wielu źródeł jednocześnie. Może się zdarzyć, że kilka reguł z różnych źródeł będzie próbowało ustawić wartość tej samej właściwości w tym samym elemencie. Która z nich powinna zwyciężyć? Na to pytanie odpowiadają trzy fundamentalne mechanizmy arkuszy stylów:
Cechy te są szczegółowo opisywane w module "CSS Cascading and Inheritance Level 3", który ma już status kandydującej rekomendacji. Część informacji pochodzi także ze specyfikacji "Selectors Level 3" i innych nawiązujących dokumentów. Najnowsze opisy są zdecydowanie bardziej rozbudowane niż materiały zawarte w poprzednim standardzie "CSS 2.1 - Assigning property values, Cascading, and Inheritance".
Zrozumienie tych mechanizmów będzie kluczowe do swobodnego poruszanie się po CSS, dlatego postaram się wyjaśnić zagadnienie najlepiej jak potrafię.
Opis właściwości#
Każda właściwość definiowana przez standard CSS charakteryzowana jest przy użyciu specjalnej tabelki, w której zawarte są najważniejsze cechy danej właściwości. Tabelka dla przykładowej właściwości background-color
wygląda następująco:
Name: | background-color |
---|---|
Value: | <color> |
Initial: | transparent |
Applies to: | all elements |
Inherited | no |
Percentages | N/A |
Media | visual |
Computed value | the computed color(s) |
Animatable | yes |
Jeśli dojdę do etapu opisu różnych właściwości w moim kursie CSS, to tabelki charakteryzujące właściwości umieszczę w oryginalnej postaci (bez tłumaczenia). Dzięki temu uniknę potencjalnie błędnej interpretacji w tym kluczowym miejscu.
Kilka uwag odnośnie poszczególnych cech:
- Skrót
"N/A"
oznacza "not available" lub "not applicable", czyli niedostępny lub nie mający zastosowania dla tej cechy. - Każda właściwość ma jakąś wartość początkową (wiersz z nagłówkiem Initial), która z punktu widzenia przetwarzania wartości może stanowić wartość określoną. Nawet tabelkowy opis typu
"Initial: none"
oznacza, że wartość początkowa występuje, z tym że jest nią słowo kluczowe"none"
, które jest poprawną wartością w niektórych właściwościach CSS.
Skrócone właściwości#
Niektóre właściwości są skróconymi właściwościami # (shorthand properties), co oznacza, że pozwalają one autorom na określenie wartości kilku właściwości za pomocą pojedynczej właściwości. Skrócona właściwość ustawia wszystkie swoje cząstkowe wydłużone właściwości # (longhand sub-properties), dokładnie tak, jakby zostały podane w pełnej formie.
Dla przykładu, właściwość font
jest skróconą właściwością dla jednoczesnego ustawienia font-style
, font-variant
, font-weight
, font-size
, line-height
i font-family
. Poniżej zamieszczam dwa równoważne zapisy:
h1 {
font-weight: bold;
font-size: 12pt;
line-height: 14pt;
font-family: Helvetica;
font-variant: normal;
font-style: normal;
}
h1 {font: bold 12pt/14pt Helvetica;}
Kiedy pewne wartości zostaną pominięte w skróconej formie, to o ile nie zdefiniowano inaczej, każda "brakująca" cząstkowa właściwość jest przypisywana ze swoją wartością początkową.
Oznacza to tyle, że deklaracje skróconych właściwości zawsze ustawiają wszystkie swoje cząstkowe właściwości, nawet te, które nie zostały wyraźnie ustawione. Nieodpowiednie stosowanie tego mechanizmu może doprowadzić do przypadkowego zresetowania niektórych cząstkowych właściwości. Dla przykładu, zapisanie background: green
zamiast background-color: green
powoduje, że kolor tła nadpisze wszelkie poprzednie deklaracje, które mogły ustawiać tło w postaci obrazka.
W niektórych przypadkach skrócona właściwość może mieć odrębną składnię lub specjalne słowa kluczowe, które nie odpowiadają bezpośrednio wartościom swoich cząstkowych właściwości. Sytuacje takie będą dokładnie określane przy definiowaniu skróconych właściwości.
Jeśli skrócona właściwość jest określona jako jedno z CSS-owych rozszerzających słów kluczowych, to ustawia wszystkie swoje cząstkowe właściwości na to słowo kluczowe. Należy pamiętać, że te słowa kluczowe nie mogą być łączone z innymi wartościami w pojedynczej deklaracji, nawet w skróconej właściwość.
Oznaczenie skróconej właściwość za pomocą adnotacji @important
jest równoważne z oznaczeniem wszystkich jej cząstkowych właściwości adnotacją !important
.
Resetowanie wszystkich właściwości: właściwość all#
Name: | all |
---|---|
Value: | initial | inherit | unset |
Initial: | See individual properties |
Applies to: | See individual properties |
Inherited | See individual properties |
Percentages | See individual properties |
Media | See individual properties |
Computed value | See individual properties |
Animatable | See individual properties |
Właściwość all
# jest skróconą właściwością, która resetuje wszystkie właściwości CSS, z wyjątkiem direction
i unicode-bidi
. Akceptowanymi wartościami są jedynie CSS-owe rozszerzające słowa kluczowe (zobacz opis dla initial
, inherit
i unset
).
Wykluczone właściwości są aktualnie funkcjami na poziomie znaczników i nie powinny być ustawiane w arkuszu stylów autora. Istnieją one tylko jako właściwości CSS do formatowania języków dokumentów nieobsługiwanych przez aplikacje klienckie. W zamian autorzy powinni używać odpowiednich znaczników, jak np. HTML-owy atrybut dir
.
Dla przykładu, kiedy autor zadeklaruje all: initial
na elemencie, to zablokuje wszystkie dziedziczenia i zresetuje wszystkie właściwości, jak gdyby żadne zasady nie pojawiły się w kaskadzie na poziomie autora, użytkownika lub aplikacji klienckiej.
To może być szczególnie użyteczne w przypadku dołączania do strony widżetów pochodzących od osób trzecich. Załóżmy, że mamy już zdefiniowane własne style, i niektóre z nich są aplikowane dla wszystkich elementów <div>
. Zapragnęliśmy dodania jakiegoś ciekawego widżetu, ale ze stylami jego autora. Nasze style mogą się gryźć ze stylami widżetu, dlatego najlepiej jest je zresetować. Tworzymy dla widżetu pojemnik z identyfikatorem, po czym ustawiamy dla niego deklarację all: initial
. Należy przy tym pamiętać, że wszystkie "domyślne" style aplikowane do tego elementu (np. dispaly: block
z arkusza aplikacji klienckiej na elementach typu <div>
) również przepadną. W razie problemów należałoby ponownie ustawić niektóre właściwości na prawidłowe wartości.
Jeśli zależy nam na zachowaniu dziedziczonych wartości z jednoczesnym zresetowaniem wartości zadeklarowanych można skorzystać z polecenia all: unset
. Wariant all:inherit
, choć możliwy, wydaje się mało praktyczny.
Przetwarzanie wartości#
Kiedy aplikacja kliencka sparsuje dokument i skonstruuje drzewo dokumentu, to musi przypisać do każdego elementu w drzewie i do odpowiadającego mu pojemnika w strukturze formatowania, wartość dla każdej właściwości, która ma zastosowanie do docelowego typu medialnego.
Ostateczna wartość właściwości CSS dla danego elementu lub pudełka jest rezultatem wieloetapowych obliczeń:
- Po pierwsze, wszystkie wartości zadeklarowane stosowane do elementu zostają zgromadzone, dla każdej właściwości na każdym elemencie. Może być zero lub wiele wartości zadeklarowanych stosowanych do elementu.
- Kaskadowość dostarcza wartość kaskadową. Istnieje co najwyżej jedna wartość kaskadowa dla każdej właściwości w każdym elemencie.
- Domyślność dostarcza wartość określoną. Każdy element ma dokładnie jedną wartość określoną dla każdej właściwości.
- Rozwiązywanie zależnych wartości dostarcza wartość obliczoną. Każdy element ma dokładnie jedną wartość obliczoną dla każdej właściwości.
- Formatowanie dokumentu dostarcza wartość używaną. Element ma wartość używaną dla danej właściwości tylko wtedy, gdy właściwość ta ma zastosowanie do elementu.
- Wreszcie, wartość używana jest przekształcana do wartości aktualnej w oparciu o ograniczenia środowiska wyświetlającego. Podobnie jak w przypadku wartości używanej, może być lub może nie być wartości aktualnej dla danej właściwości w elemencie.
Wartości zadeklarowane#
Każda deklaracja właściwości stosowana do elementu wnosi wartość zadeklarowaną # (declared value) dla tej powiązanej z elementem właściwości. Więcej szczegółów znajdziesz w filtrowaniu deklaracji.
Wartości te są następnie przetwarzane przez kaskadę w celu wybrania pojedynczej "zwycięskiej wartości".
Wartości kaskadowe#
Rezultatem działania kaskady jest wartość kaskadowa # (cascaded value); jest to wartość zadeklarowana, która wygrywa kaskadę (zajmuje pierwsze miejsce na wyjściu kaskady). Jeśli wyjście kaskady jest pustą listą, to wartość kaskadowa nie istnieje.
Wartości określone#
Wartość określona # (specified value) jest wartością podawaną dla właściwości, którą autorzy arkuszy stylów wprowadzili świadomie dla elementu. Jest ona rezultatem wprowadzenia kaskadowej wartości na wskroś z procesem domyślności, gwarantującym, że wartość określona istnieje dla każdej właściwości w każdym elemencie.
W wielu przypadkach wartością określoną jest wartość kaskadowa. Jednakże, jeśli wartość kaskadowa nie występuje w ogóle, to wartość określona pojawia się zawsze (domyślnie). Słowa kluczowe initial
i inherit
są traktowane szczególnie, kiedy stanowią wartość kaskadową dla właściwości.
Wartości obliczone#
Wynikiem rozwiązywania wartości określonej jest wartość obliczona # (computed value), jak zdefiniowano w linii "Computed value"
przy tabelkowym opisie każdej właściwości, zazwyczaj absolutyzowana celem przygotowania do dziedziczenia.
Wartość obliczona jest wartością, która jest przekazywana z rodzica do dziecka w trakcie dziedziczenia. Ze względów historycznych nie zawsze jest ona zgodna z wartością zwracana przez metodę getComputedStyle()
.
Dla przykładu, wartość określona może być absolutna (tj. bez relacji z inną wartością, jak np. red
lub 2mm
) lub względna (tj. w relacji z inną wartością, jak np. auto
lub 2em
). Generalnie absolutyzacja relatywnej wartości obliczonej wygląda następująco:
- Wartości z jednostkami względnymi (
em
,ex
,vh
,vw
) muszą stać się absolutnymi na zasadzie przemnożenia przez rozmiar odniesienia. - Niektóre słowa kluczowe (np.
smaller
lubbolder
) muszą zostać zamienione zgodnie z ich definicjami. - Procenty w niektórych właściwościach należy przemnożyć przez wartość odniesienia (zdefiniowaną przez właściwość).
- Poprawne względne adresy URL muszą zostać rozwinięte, aby stały się bezwzględnymi.
Zwróć uwagę na warianty (f), (g) i (h) w przykładowej tabeli.
Ogólnie rzecz biorąc wartość obliczona rozwiązuje wartość określoną tak szybko, jak to możliwe, bez wpływu na dokument lub wydajność innych kosztownych lub trudnych do zrównoleglenia operacji, takich jak rozwiązywanie żądań sieciowych lub pobieranie wartości niepochodzących z elementu i jego rodzica.
Wartość obliczona istnieje nawet wtedy, gdy właściwość nie ma zastosowania (jak zdefiniowano w linii "Applies to"
przy tabelkowym opisie każdej właściwości). Jednakże, niektóre właściwości mogą zmieniać sposób, w jaki ustalają wartość obliczoną, w oparciu o to, czy właściwość ma zastosowanie dla danego elementu.
Wartości używane#
Wartość używana # (used value) jest wynikiem pobrania wartości obliczonej i ukończenia pozostałych obliczeń by uczynić ją teoretyczną absolutną wartością używaną w układzie dokumentu. Jeśli właściwość nie ma zastosowania w danym elemencie, to element nie posiada wartości używanej dla tej właściwości.
Dla przykładu, deklaracja typu width: auto
nie może być rozwinięta do długości bez znajomości układu przodków elementu, więc wartością obliczoną jest auto
, kiedy wartością używaną jest długość absolutna, taka jak 100px
.
W innym przykładzie, element <div>
może mieć wartość obliczoną auto
dla właściwości break-before
, ale nabywa wartość używaną page
poprzez propagację z jego pierwszego dziecka.
W końcu, jeśli właściwość nie ma zastosowania do elementu, to nie ma wartości używanej; więc, dla przykładu, właściwość flex
nie posiada wartości używanej w elementach, które nie są zaliczane do elastycznych składników.
Wartości aktualne#
Wartość używana jest zasadniczo gotowa do użytku, ale aplikacja kliencka może nie być w stanie korzystać z tej wartości w danym środowisku. Dla przykładu, aplikacja kliencka może być zdolna tylko do renderingu obramowania z całkowitą szerokością pikselową (bez ułamków), a zatem może wykonać aproksymację używanej szerokości. Również rozmiar fontu w elemencie może wymagać dostosowania bazującego na podstawie dostępności fontów lub wartości we właściwości font-size-adjust
. Wartość aktualna # (actual value) jest wartością używaną po przeprowadzeniu wszelkich takich korekt.
Poprzez pomiar wartości aktualnych w elementach można wiele się nauczyć o tym, jak dokument jest konstruowany na zewnątrz. Jednakże, nie wszystkie informacje są rejestrowane w wartościach aktualnych. Dla przykładu, wartość aktualna dla właściwości page-break-after
nie odzwierciedla, czy istnieje lub nie istnieje podział strony po elemencie. Podobnie wartość aktualna właściwości orphans
nie odzwierciedla liczby osieroconych linii w pewnym elemencie. Zwróć uwagę na warianty (j) i (k) w przykładowej tabeli.
Tabela z przykładami#
Poniższa tabela powinna ułatwić zrozumienie różnic między poszczególnymi rodzajami wartości we właściwościach.
Właściwość | Zwycięska deklaracja | Wartość kaskadowa | Wartość określona | Wartość obliczona | Wartość używana | Wartość aktualna | |
---|---|---|---|---|---|---|---|
(a) # | text-align | text-align: left | left | left | left | left | left |
(b) # | border-top-width, border-right-width, border-bottom-width, border-left-width | border-width: inherit | inherit | 4.2px | 4.2px | 4.2px | 4px |
(c) # | width | (none) | (none) | auto (wartość początkowa) | auto | 120px | 120px |
(d) # | list-style-position | list-style-position: inherit | inherit | inside | inside | inside | inside |
(e) # | list-style-position | list-style-position: initial | initial | outside (wartość początkowa) | outside | outside | outside |
(f) # | font-size | font-size: 1.2em | 1.2em | 1.2em | 14.1px | 14.1px | 14px |
(g) # | width | width: 80% | 80% | 80% | 80% | 354.2px | 354px |
(h) # | width | width: auto | auto | auto | auto | 134px | 134px |
(i) # | height | height: auto | auto | auto | auto | 176px | 176px |
(j) # | page-break-after | (none) | (none) | auto (wartość początkowa) | auto | auto | auto |
(k) # | orphans | orphans: 3 | 3 | 3 | 3 | 3 | 3 |
Filtrowanie#
W celu odnalezienia wartości zadeklarowanych implementacje muszą najpierw zidentyfikować wszystkie deklaracje, które są stosowane do każdego elementu. Deklaracja jest stosowana do elementu # (applies to an element) jeśli spełnia następujące warunki filtracji:
- Należy do arkusza stylów, który obecnie stosuje się do aktualnego dokumentu.
- Nie jest określona przez regułę warunkową z fałszywym stanem.
- Należy do reguły stylu, której selektor pasuje do elementu (z uwzględnieniem zawężenia w razie konieczności).
- Jest poprawna składniowo: właściwość deklaracji jest znaną nazwą właściwości, i wartość deklaracji pasuje do składni dla tej właściwości.
Wartości z deklaracji mających zastosowanie, dla każdej właściwości w każdym elemencie, są listami wartości zadeklarowanych. Kolejna sekcja, kaskada, priorytetyzuje te listy.
Kaskadowość#
Kaskada # (cascade) pobiera nieuporządkowaną listę wartości zadeklarowanych dla danej właściwości w danym elemencie, sortuje je względem pierwszeństwa deklaracji opisanej niżej, i zwraca pojedynczą wartość kaskadową.
Kaskada sortuje deklaracje według następujących kryteriów, w kolejności malejącego znaczenia:
- Pochodzenie i Ważność (Origin and Importance) #
Pochodzenie deklaracji jest zależne od jej źródła przybycia i jej ważność jest zależna od użycia lub pominięcia adnotacji
!important
. Nadrzędność różnych pochodzeń jest następująca, w kolejności malejącego znaczenia:- Deklaracje przejść ("CSS Transitions")
- Deklaracje aplikacji klienckiej oznaczone ważnością.
- Deklaracje użytkownika oznaczone ważnością.
- Deklaracje nadpisujące oznaczone ważnością ("DOM Level 2 Style Specification").
- Deklaracje autora oznaczone ważnością.
- Deklaracje animacji ("CSS Animations").
- Normalne deklaracje nadpisujące ("DOM Level 2 Style Specification").
- Normalne deklaracje autora.
- Normalne deklaracje użytkownika.
- Normalne deklaracje aplikacji klienckiej.
Deklaracje z pochodzeń umieszczonych wcześniej na tej liście wygrywają z deklaracjami pochodzeń wymienianych dalej.
- Zawężenie (Scope) #
Deklaracja może być zawężona # (scoped) do poddrzewa dokumentu tak, że wpływa tylko na zawężający element # (scoping element) i potomków tego elementu. Dla przykładu, HTML5 definiuje zawężenie elementów
<style>
, których arkusze stylów są zawężone do rodzica tego elementu.Jeśli zawężające elementy dwóch deklaracji mają relacje przodka/potomka, to dla normalnych reguł wygrywa deklaracja, której zawężającym elementem jest potomek, i dla reguł oznaczonych ważnością wygrywa deklaracja, której zawężającym elementem jest przodek.
Innymi słowy, dla normalnych deklaracji nadpisujące są wewnętrzne deklaracje zawężenia, ale dla reguł
!important
nadpisujące są zewnętrzne zawężenia.Również w tym etapie, wszystkie niezawężone deklaracje uznawane są za zawężone do elementu korzenia. Normalne deklaracje pochodzące z atrybutów stylu uznawane są za zawężone do elementu z tym atrybutem, podczas gdy deklaracje oznaczone ważnością pochodzące z atrybutów stylu uznawane są za zawężone do elementu korzenia ("CSS Style Attributes").
Ta dziwna obsługa deklaracji oznaczanych przez
!important
w atrybucie stylu powstała ze względu na dostosowanie do zachowania zdefiniowanego w CSS1 i CSS2, gdzie atrybuty stylu miały po prostu wyższą specyficzność niż jakiekolwiek inne reguły autora.- Specyficzność (Specificity) #
Dokument "Selectors Level 3" opisuje w jaki sposób obliczyć specyficzność selektora. Każda deklaracja ma taką samą specyficzność, jak reguła stylu w której się pojawia. Również w tym etapie deklaracje nienależące do reguł stylu (takie jak zawartości atrybutu stylu) uważa się za posiadające specyficzność wyższą niż jakikolwiek selektor. Deklaracje z najwyższą specyficznością zwyciężają.
- Kolejność występowania (Order of Appearance) #
Wygrywa ostatnia deklaracja zgodnie z kolejnością występowania w dokumencie. W tym celu:
- Deklaracje z importowanych arkuszy stylów są kolejkowane tak, jakby ich arkusze stylów zostały podstawione w miejscu reguły
@import
. - Deklaracje z arkuszy stylów niezależnie podlinkowanych przez źródłowy dokument traktowane są tak, jakby zostały połączone w kolejności podlinkowania, jak określono w języku dokumentu gospodarza.
- Deklaracje z atrybutów stylu są traktowane zgodnie z kolejnością pojawiania się atrybutu stylu w elemencie, i wszystkie są umieszczane za jakimikolwiek arkuszami stylów.
- Deklaracje z importowanych arkuszy stylów są kolejkowane tak, jakby ich arkusze stylów zostały podstawione w miejscu reguły
W ostateczności wyjście kaskady # (output of the cascade) jest (potencjalnie pustą) posortowaną listą wartości zadeklarowanych dla każdej właściwości w każdym elemencie.
Kaskadowość pochodzeń#
Każda reguła stylu ma pochodzenie # (origin), określające w którym miejscu wejdzie do kaskady. CSS definiuje trzy podstawowe pochodzenia:
- Autor (Author) #
Autor określa arkusze stylów dla dokumentu źródłowego zgodnie z konwencjami języka dokumentu. Dla przykładu, w HTML, arkusze stylów mogą być osadzone w dokumencie lub zewnętrznie podlinkowane.
- Użytkownik (User) #
Użytkownik może mieć możliwość określania informacji o stylach dla danego dokumentu. Dla przykładu, użytkownik może określić plik zawierający arkusz stylów lub aplikacja kliencka może dostarczyć interfejs do generacji arkusza stylów użytkownika (lub zachowywać się tak, jakby to robiła).
- Aplikacja kliencka (User agent) #
Zgodne aplikacje klienckie muszą stosować domyślny arkusz stylów (lub zachowywać się tak, jakby to robiły). Domyślny arkusz stylów w aplikacji klienckiej powinien prezentować elementy języka dokumentu w sposób spełniający ogólne wymogi prezentacyjne dla języka dokumentu (np. dla wizualnych przeglądarek, element
EM
w HTML-u jest prezentowany przy użyciu kursywy).Zobacz też "HTML5 - The CSS user agent style sheet and presentational hints".
Rozszerzenia dla CSS definiują następujące dodatkowe pochodzenia:
- Nadpisujące (Override)
Specyfikacja "DOM Level 2 Style" definiuje interfejs "nadpisujących" stylów, które wchodzą w kaskadę na wyższym poziomie niż pozostałe reguły autora.
- Animacje (Animation)
Moduł "CSS Animations" generuje "wirtualne" reguły reprezentujące ich efekty w czasie uruchomienia.
- Przejścia (Transition)
Podobnie jak wyżej, moduł "CSS Transitions" generuje "wirtualne" reguły reprezentujące ich efekty w czasie uruchomienia.
Ważne deklaracje: adnotacja !important#
CSS próbuje utworzyć równowagę sił pomiędzy arkuszami stylów autora i użytkownika. Domyślnie, reguły w arkuszu stylów autora nadpisują te zawarte w arkuszu stylów użytkowania, które z kolei nadpisują reguły zawarte w domyślnym arkuszu stylów aplikacji klienckiej.
Aby to zrównoważyć, deklaracja może być oznaczona jako ważna # (important), co zwiększa jej znaczenie w kaskadzie i odwraca kolejność pierwszeństwa.
Deklaracja jest ważna jeśli posiada adnotację !important
, tzn. jeśli dwa ostatnie słowa (z wykluczeniem spacji i komentarzy) w jej wartości stanowią zakończenie w postaci słowa "!"
po którym następuje identyfikator słowa "important"
.
Prosty przykład:
div {dispaly: none !important;}
Ważna deklaracja ma pierwszeństwo przed normalną deklaracją. Arkusze stylów autora i użytkownika mogą zawierać deklaracje oznaczane przez !important
, gdzie ważne deklaracje użytkownika są nadrzędne względem ważnych deklaracji autora. Ta funkcja CSS poprawia dostępność dokumentów oferując użytkownikom dodatkową formę kontroli nad prezentacją (większe fonty, kombinacje kolorów, itp.).
Ważne deklaracje ze wszystkich pochodzeń mają pierwszeństwo przed animacjami. Dzięki temu autorzy mogą nadpisywać animowane wartości w kluczowych przypadkach. Domyślnie animowane wartości nadpisują wszystkie pozostałe reguły. Warto podkreślić, że uwaga ta nie dotyczy reguł przejść, które znajdują się na szczycie kaskady (niezależnie od adnotacji !important
).
Arkusze stylów w aplikacjach klienckich również mogą zawierać ważne deklaracje. W takiej sytuacji nadpisują one wszystkie deklaracje autora i użytkownika (dotyczy to zwykłych jak i ważnych deklaracji).
Prosty przykład:
/* Arkusz stylów użytkownika */
p {text-indent: 1em !important;}
p {font-style: italic !important;}
p {font-size: 18pt;}
/* Arkusz stylów autora */
p {text-indent: 1.5em !important;}
p {font: normal 12pt sans-serif !important;}
p {font-size: 24pt;}
W powyższym przykładzie pierwsza reguła w arkuszu stylów użytkownika zawiera adnotację !important
, przez co nadpisują odpowiadającą deklarację w arkuszu stylów autora. Deklaracja z drugiej reguły także zwycięży ze względu na oznaczenie przez !important
. Jednakże, trzecia deklaracja w arkuszu stylów użytkownika nie jest ważna, i dlatego przegrywa z drugą regułą w arkuszu stylów autora (która ustawia style w postaci skróconej właściwości). Ponadto, trzecia reguła autora przegrywa z drugą regułą autora, ponieważ druga deklaracja jest oznaczona przez !important
. To pokazuje, że ważne deklaracje mogą być przydatne także w arkuszach stylów autora.
Pierwszeństwo dla nie CSS-owych wskazówek prezentacyjnych#
Aplikacja kliencka może wybrać pierwszeństwo dla wskazówek prezentacyjnych umieszczanych bezpośrednio w strukturze znacznikowej dokumentu, jak w przypadku atrybutu bgcolor
lub elementu <s>
z HTML-a. Wszystkie dokumenty bazujące na językach stylizacji muszą zostać zamienione na odpowiadające reguły CSS, i albo wchodzą one do kaskady na poziomie aplikacji klienckiej, albo są traktowane jak reguły na poziomie autora z zerową specyficznością, umieszczone na początku arkusza stylów autora.
Język dokumentu może określać, czy prezentacyjna wskazówka wchodzi do kaskady na poziomie aplikacji klienckiej lub autora; jeśli tak jest, to aplikacja kliencka musi być z tym zgodna. Dla przykładu, "SVG 1.1 (Second Edition)" mapuje swoje atrybuty prezentacyjne do poziomu autora.
Prezentacyjne wskazówki wchodzące w kaskadę na poziomie aplikacji klienckiej mogą być nadpisane przez reguły autora lub użytkownika. Prezentacyjne wskazówki wchodzące w kaskadę na poziomie autora mogą być nadpisane przez style autora, ale nie przez reguły użytkownika bez oznaczenia !important
. Języki gospodarza powinny wybrać odpowiedni poziom dla prezentacyjnych podpowiedzi, zgodnie z powyższymi zaleceniami.
Domyślność#
Kiedy kaskada nie zwraca wyniku w postaci wartości, to wartość określona musi być znaleziona w inny sposób. Dziedziczone właściwości wyciągają swoje domyślne wartości ze swoich elementowych rodziców w drodze dziedziczenia; wszystkie inne właściwości pobierają swoją wartość początkową. Autorzy mogą jawnie zażądać dziedziczenia lub inicjalizacji poprzez słowa kluczowe inherit
i initial
.
Wartości początkowe#
Każda właściwość ma wartość początkową # (initial value), nazywaną też wartością domyślną lub wartością inicjującą, która definiowana jest w tabelkowym opisie. Jeśli właściwość nie jest dziedziczoną właściwością i kaskada nie zwraca wyniku w postaci wartości, to wartością określoną właściwości jest jej wartość początkowa.
Dziedziczenie#
Dziedziczenie # (inheritance) polega na przekazywaniu wartości właściwości z elementów rodziców do ich dzieci. Wartość dziedziczona # (inherited value) właściwości w elemencie jest wartością obliczoną właściwości w elemencie rodzica tego elementu. Dla elementu korzenia, który nie posiada elementu rodzica, wartość dziedziczona jest wartością początkową właściwości.
Pseudoelementy dziedziczą z fikcyjnego elementu opisywanego dla każdego pseudoelementu (zgodnie ze specyfikacją "Selectors Level 3").
Niektóre właściwości są dziedziczonymi właściwościami # (inherited properties), jak określono w ich tabelkowym opisie. Oznacza to tyle, że dopóki kaskada nie zwraca wyniku w postaci wartości, to wartość będzie ustalana w drodze dziedziczenia.
Właściwość może być również jawnie dziedziczona. Zobacz słowo kluczowe inherit
.
Należy pamiętać, że dziedziczenie przebiega po drzewie dokumentu i nie jest przechwytywane przez anonimowe pudełka, lub w inny sposób dotkniętego przez manipulacje drzewa pudełkowego.
Jawna domyślność#
Niektóre CSS-owe rozszerzające wartości właściwości są definiowane poniżej; deklaracja właściwości z tymi wartościami jawnie określa domyślne zachowanie. Jak opisano w module "CSS Values and Units Level 3", wszystkie właściwości CSS mogą przyjąć te wartości.
Resetowanie właściwości: słowo kluczowe initial#
Jeśli wartość kaskadowa jest słowem kluczowym initial
#, to wartość początkowa właściwości staje się jej wartością określoną.
Przydaje się to w chwili, kiedy mamy zdefiniowane konkretne style, ale dla pewnych elementów chcemy zastosować wartości początkowe.
Prosty przykład:
<!DOCTYPE html>
<html>
<head>
<style>
.red {color: red;}
.initial {color: initial;}
</style>
</head>
<body>
<p class="red">
Ten tekst jest czerwony
<em class="initial">a ten używa koloru początkowego (w tym
wypadku czarnego)</em>
ten tekst jest znowu czerwony.
</p>
</body>
</html>
Jest to szczególnie użyteczne w przypadku dynamicznych zmian CSS. Załóżmy, że za pomocą JS zmieniamy sposób wyświetlania (właściwość display
) jakiegoś elementu. Po skończonych obliczeniach i modyfikacjach pragniemy przywrócić wyświetlanie do domyślnego. Sęk w tym, że różne elementy mają różne domyślne sposoby wyświetlania, i jeśli ich nie znamy, albo nie podeprzemy się jakąś dokumentacją, to ustawiając błędną z nich możemy całkowicie zepsuć układ naszej strony. Dzięki wartości initial
problem zostaje rozwiązany.
Słowo kluczowe initial
dla właściwości display
zawsze przypisze wartość inline
(bo jest ona wartością początkową dla właściwości display
), dlatego powyższa porada sprawdzi się jedynie w przypadku elementów wyświetlanych w linii.
Nie należy zapominać również o tym, że w przypadku niektórych właściwości ich wartość początkowa zależy od aplikacji klienckiej (jak podają poszczególne specyfikacje CSS). Dlatego też nigdy nie będzie gwarancji, że użycie wartości initial
zapewni identyczny efekt w każdym programie.
Jawne dziedziczenie: słowo kluczowe inherit#
Jeśli wartość kaskadowa jest słowem kluczowym inherit
#, to wartość dziedziczona właściwości staje się jej wartością określoną i wartością obliczoną.
Trzeba zdawać sobie sprawę z tego, że nie wszystkie właściwości są domyślnie dziedziczone (np. border
czy margin
). Jeśli będzie nam zależało na ich dziedziczeniu, to możemy je wymusić właśnie dzięki specjalnej wartości inherit
.
Prosty przykład:
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 10px;
border: 1px solid #000;
}
p {
border: inherit; /* Użyj tego samego obramowania jak rodzić */
}
</style>
</head>
<body>
<div>Element BODY ma ustawione obramowanie, ale nie jest ono
dziedziczone w elementach DIV.</div>
<p>Wymuszamy dziedziczenie obramowania z elementu BODY do elementów P.</p>
<p>Ten akapit również odziedziczy obramowanie.</p>
<pre>Ale element PRE już nie.</pre>
<div>Kolejny element DIV z zagnieżdżonym akapitem.
<p>Akapit nie ma obramowania, bo jego rodzicem jest teraz DIV, a nie BODY.</p>
</div>
</body>
</html>
Zwracam uwagę na ostatni przypadek, czyli akapit umieszczony wewnątrz bloku. Akapit dalej dziedziczy obramowanie, ale ze swojego rodzica, którym w tym momencie jest element <div>
nieposiadający żadnego obramowania (a dokładniej, właściwości obramowania bloku mają domyślne wartości, które czynią je niewidocznym). Blok nie dziedziczy obramowania z ciała dokumentu, bo domyślnie obramowanie nie jest dziedziczoną właściwością, a wymuszenie dziedziczenia obramowania określiliśmy jedynie dla akapitów.
W praktyce większość użytecznych właściwości jest domyślnie dziedziczona (np. cechy fontów lub kolorów), dlatego stosowanie wartości inherit
jest rzadkością.
Czyszczenie wszystkich deklaracji: słowo kluczowe unset#
Jeśli wartość kaskadowa jest słowem kluczowym unset
#, a następnie, jeśli jest dziedziczoną właściwością, to jest traktowana jak inherit
, a jeśli nie, to jest traktowana jak initial
. To słowo kluczowe skutecznie usuwa wszystkie wartości zadeklarowane występujące wcześniej w kaskadzie, prawidłowo odziedziczone lub nieodpowiednie dla właściwości (lub wszystkie rozwinięcia w skróconych).
Prosty przykład:
<!DOCTYPE html>
<html>
<head>
<style>
body {color: blue;}
p {border: 5px solid green; background-color: yellow;}
#target {all: unset;}
</style>
</head>
<body>
<p>Akapit bez identyfikatora. Powinien mieć niebieski tekst
(dziedziczy z BODY), żółte tło oraz zielone obramowanie.</p>
<p id="target">Akapit z atrybutem id="target". Powinien mieć niebieski tekst
(dziedziczy z BODY) oraz początkowe tło i obramowanie.</p>
</body>
</html>
Wartość unset
jest szczególna (działa hybrydowo) i zasadniczo przydaje się w pewnych okolicznościach razem z właściwością all
. Na chwilę obecną jest obsługiwana jedynie przez przeglądarkę Firefox.