Podcast CSS – 003: szczegółowość
Załóżmy, że pracujesz z tymi kodami HTML i CSS:
<button class="branding">Hello, Specificity!</button>
.branding {
color: blue;
}
button {
color: red;
}
Są tu 2 reguły, które kierują na ten sam element. Każda reguła zawiera deklarację, która ma ustawić kolor przycisku: jedna próbuje ustawić kolor czerwony, a druga – niebieski. Która deklaracja zostanie zastosowana do elementu?
Zrozumienie algorytmu szczegółowości CSS jest kluczem do zrozumienia, jak CSS decyduje między konkurującymi deklaracjami.
Szczegółowość to jeden z odrębnych etapów kaskady, który został omówiony w ostatnim module dotyczącym kaskady.
Ocena szczegółowości
Każda reguła selektora w źródle otrzymuje ocenę. Szczegółowość można traktować jako łączny wynik, a każdy typ selektora dodaje punkty do tego wyniku. Deklaracje z reguł o najwyższej szczegółowości wygrywają.
W przypadku szczegółowości w prawdziwym projekcie należy zadbać o to, aby reguły CSS, które mają być stosowane, rzeczywiście były stosowane, a jednocześnie utrzymywać niskie wyniki, aby uniknąć złożoności. Szczegółowość powinna być tylko tak wysoka, jak jest to konieczne, a nie jak najwyższa. W przyszłości może być konieczne zastosowanie ważniejszych reguł CSS. Jeśli wybierzesz najwyższą szczegółowość, utrudnisz sobie to zadanie.
Szczegółowość nie jest liczbą dziesiętną, ale triadą składającą się z 3 komponentów: A, B i C.
A: szczegółowość podobna do identyfikatoraB: szczegółowość podobna do klasyC: szczegółowość podobna do elementu
Często jest ona reprezentowana za pomocą notacji (A,B,C). Na przykład: (1,0,2).
Powszechnie używana jest też notacja alternatywna A-B-C.
Porównywanie szczegółowości
Szczegółowości są porównywane przez porównanie 3 komponentów w kolejności: szczegółowość z większą wartością A jest bardziej szczegółowa; jeśli 2 wartości A są równe, to szczegółowość z większą wartością B jest bardziej szczegółowa; jeśli 2 wartości B są również równe, to szczegółowość z większą wartością C jest bardziej szczegółowa; jeśli wszystkie wartości są równe, to 2 szczegółowości są równe.
Na przykład (1,0,0) jest uważana za wyższą szczegółowość niż (0,4,3)
ponieważ wartość A w (1,0,0) (czyli 1)
jest większa niż wartość A w (0,4,3) (czyli 0).
Selektory wpływają na szczegółowość
Każda część triady szczegółowości zaczyna się od wartości 0,
więc domyślna szczegółowość to (0,0,0).
Każda część selektora zwiększa szczegółowość, która w zależności od typu selektora zwiększa wartość A, B lub C.
Selektor uniwersalny
Selektor uniwersalny (*)
**nie dodaje szczegółowości** , pozostawiając jej wartość na początkowej szczegółowości (0,0,0).
* {
color: red;
}
Selektor elementu lub pseudoelementu
Selektor elementu (typu)
lub pseudoelementu
dodaje szczegółowość podobną do elementu, która zwiększa komponent C o 1.
Poniższe przykłady mają ogólną szczegółowość (0,0,1).
Selektor typu
div {
color: red;
}
Selektor pseudoelementu
::selection {
color: red;
}
Selektor klasy, pseudoklasy lub atrybutu
Selektor klasy,
pseudoklasy lub
atrybutu dodaje szczegółowość podobną do klasy
, która zwiększa komponent B o 1.
Poniższe przykłady mają szczegółowość (0,1,0).
Selektor klasy
.my-class {
color: red;
}
Selektor pseudoklasy
:hover {
color: red;
}
Selektor atrybutu
[href='#'] {
color: red;
}
Selektor identyfikatora
Selektor identyfikatora
dodaje szczegółowość podobną do identyfikatora, która zwiększa komponent A o 1,
o ile używasz selektora identyfikatora (#myID), a nie selektora atrybutu ([id="myID"]).
W poniższym przykładzie szczegółowość wynosi (1,0,0).
#myID {
color: red;
}
Inne selektory
CSS ma wiele selektorów. Nie wszystkie z nich dodają szczegółowość.
Na przykład pseudoklasa :not()
sama w sobie nie dodaje nic do obliczania szczegółowości.
Szczegółowość pseudoklasy :not() jest zastępowana szczegółowością najbardziej szczegółowego selektora w jej rozdzielonym przecinkami argumencie selektorów, co daje taką samą szczegółowość, jakby została zapisana jako :not(:is(argument)).
div:not(.my-class) {
color: red;
}
Pseudoklasa :is() również nie dodaje nic do obliczania szczegółowości. Podobnie jak :not() przyjmuje szczegółowość najbardziej szczegółowego argumentu.
:is(h1, h2, h3) {
color: blue;
}
Ten przykład ma szczegółowość (0,0,1), ponieważ ma tylko 1 rodzaj selektora (type).
Po dodaniu id szczegółowość wzrasta do (1,0,0).
:is(h1, h2, h3, #my-heading) {
color: blue;
}
Pseudoklasa :where() jest inna. Niezależnie od szczegółowości dowolnego z jej argumentów zawsze ma szczegółowość (0,0,0).
:where(h1, h2, h3, #my-heading) {
color: blue;
}
Style o niskiej szczegółowości stosowane za pomocą :where() pozwalają zastąpić te style podstawowymi selektorami w dalszej części arkusza stylów:
:where(#my-content) {
color: red;
}
p {
color: blue;
}
Mimo że :where() ma id na liście argumentów, nadal ma tylko
szczegółowość (0, 0, 0), więc podstawowy selektor p ją zastępuje, a tekst
będzie blue.
Sprawdź swoją wiedzę
Sprawdź swoją wiedzę na temat oceny szczegółowości
Jaka jest szczegółowość a[href=/learn/css/%22#%22%5D%3C%2Fcode>?
(0,0,1)a to (0,0,1), ale wartość [href=/learn/css/%22#%22%5D%3C%2Fcode> to (0,1,0).(0,1,0)a to (0,0,1), ale wartość [href=/learn/css/%22#%22%5D%3C%2Fcode> to (0,1,0).(0,1,1)a to (0,0,1), a wartość [href=/learn/css/%22#%22%5D%3C%2Fcode> to (0,1,0), co daje łączną szczegółowość (0,1,1).Czynniki, które nie wpływają na szczegółowość
Istnieje kilka powszechnych błędnych przekonań dotyczących wpływu tych czynników na szczegółowość.
Wbudowane atrybuty stylów
CSS stosowany bezpośrednio do atrybutu style elementu,
nie wpływa na szczegółowość, ponieważ jest to inny etap kaskady
który jest oceniany przed szczegółowością.
<div style="color: red"></div>
Aby zastąpić tę deklarację w arkuszu stylów, musisz sprawić, aby deklaracja wygrała na wcześniejszym etapie kaskady.
Możesz na przykład dodać !important do niej,
aby stała się częścią źródła !important utworzonego przez autora.
Deklaracje !important
!important na końcu deklaracji CSS nie wpływa na szczegółowość
ale umieszcza deklarację w innym źródle,
czyli utworzonym przez autora !important.
W poniższym przykładzie szczegółowość .my-class nie ma znaczenia dla wygrania deklaracji !important.
.my-class {
color: red !important;
color: white;
}
Gdy 2 deklaracje są !important, szczegółowość ponownie wchodzi w grę, ponieważ etap źródła w kaskadzie nie był w stanie jeszcze określić zwycięzcy.
.branding {
color: blue !important;
}
button {
color: red !important;
}
Szczegółowość w kontekście
Gdy używany jest złożony selektor, każda jego część dodaje się do szczegółowości. Rozważ ten przykład kodu HTML:
<a class="my-class another-class" href="#">A link</a>
Ten link ma 2 klasy.
Reguła w tym kodzie CSS ma szczegółowość (0,0,1):
a {
color: red;
}
Jeśli odwołasz się do jednej z klas w selektorze,
będzie on miał szczegółowość (0,1,1):
a.my-class {
color: green;
}
Dodaj do selektora drugą klasę,
a będzie on miał szczegółowość (0,2,1):
a.my-class.another-class {
color: rebeccapurple;
}
Dodaj do selektora atrybut href,
a będzie on miał szczegółowość (0,3,1):
a.my-class.another-class[href] {
color: goldenrod;
}
Na koniec dodaj do tego :hover pseudoklasę,
a selektor będzie miał szczegółowość (0,4,1):
a.my-class.another-class[href]:hover {
color: lightgrey;
}
Sprawdź swoją wiedzę
Sprawdź swoją wiedzę na temat oceny szczegółowości
Który z tych selektorów ma szczegółowość (0,2,1)?
article > section(0,0,2).article.card.dark(0,2,1).article:hover a[href](0,0,1)), selektor atrybutu (wartość (0,1,0)) i selektor klasy (wartość (0,1,0)). Daje to łączną szczegółowość (0,2,2).Praktyczne zwiększanie szczegółowości
Załóżmy, że masz taki kod CSS:
.my-button {
background: blue;
}
button[onclick] {
background: grey;
}
Z takim kodem HTML:
<button class="my-button" onclick="alert('hello')">Click me</button>
Przycisk ma szare tło,
ponieważ drugi selektor ma szczegółowość (0,1,1).
Wynika to z tego, że ma on 1 selektor typu (button), który ma wartość (0,0,1) , oraz selektor atrybutu ([onclick]), który ma wartość (0,1,0).
Poprzednia reguła – .my-button – ma wartość (0,1,0) , ponieważ ma 1 selektor klasy, który ma niższą szczegółowość niż (0,1,1).
Jeśli chcesz zwiększyć szczegółowość tej reguły, możesz powtórzyć selektor klasy w ten sposób:
.my-button.my-button {
background: blue;
}
button[onclick] {
background: grey;
}
Teraz przycisk będzie miał niebieskie tło, ponieważ nowy selektor ma szczegółowość (0,2,0).
W przypadku remisu w szczegółowości następuje powrót do następnego etapu kaskady
Na razie kontynuujmy przykład z przyciskiem i zmieńmy kod CSS na ten:
.my-button {
background: blue;
}
[onclick] {
background: grey;
}
Przycisk ma szare tło, ponieważ oba selektory mają identyczną szczegółowość (0,1,0).
Jeśli zmienisz kolejność reguł w kodzie źródłowym, przycisk będzie niebieski.
[onclick] {
background: grey;
}
.my-button {
background: blue;
}
Wynika to z tego, że oba selektory mają taką samą szczegółowość. W tym przypadku kaskada wraca do etapu kolejności występowania.