Jak obliczane są punkty specyficzności CSS

124

Badając specyfikę, natknąłem się na tego bloga - http://www.htmldog.com/guides/cssadvanced/specificity/

Stwierdza, że ​​specyficzność jest systemem punktacji dla CSS. Mówi nam, że elementy są warte 1 punkt, klasy są warte 10 punktów, a identyfikatory są warte 100 punktów. Na górze znajduje się również stwierdzenie, że te punkty są sumowane, a ogólna kwota jest specyfiką tego selektora.

Na przykład:

body = 1 punkt
body .wrapper = 11 punktów
body .wrapper #container = 111 punktów

Tak więc, korzystając z tych punktów, spodziewam się, że następujące CSS i HTML spowodują, że tekst będzie niebieski:

#a {
    color: red;
}

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o {
  color: blue;
}
<div class="a">
  <div class="b">
    <div class="c">
      <div class="d">
        <div class="e">
          <div class="f">
            <div class="g">
              <div class="h">
                <div class="i">
                  <div class="j">
                    <div class="k">
                      <div class="l">
                        <div class="m">
                          <div class="n">
                            <div class="o" id="a">
                              This should be blue.
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Dlaczego tekst jest czerwony, skoro 15 zajęć daje 150 punktów w porównaniu z 1 identyfikatorem, który daje 100 punktów?

Najwyraźniej punkty nie są sumowane; są połączone. Przeczytaj więcej na ten temat tutaj - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

Czy to oznacza, że ​​klasy w naszym selektorze = 0,0,15,0OR 0,1,5,0?

(mój instynkt podpowiada mi, że to były, jak wiemy specyficzności wygląd selektora identyfikatora tak: 0,1,0,0)

Sam
źródło
Tutaj też jest coś dziwnego: stackoverflow.com/questions/25565928/…
Armel Larcier

Odpowiedzi:

137

Odpowiedź Pekki jest praktycznie poprawna i prawdopodobnie jest najlepszym sposobem myślenia o problemie.

Jednak, jak wielu już zauważyło, zalecenie W3C CSS stwierdza, że ​​„konkatenacja trzech liczb abc (w systemie liczbowym o dużej podstawie) daje specyficzność”. Więc maniak we mnie musiał po prostu dowiedzieć się, jak duża jest ta podstawa.

Okazuje się, że „bardzo duża baza” wykorzystywana (przynajmniej przez 4 najczęściej używane przeglądarki * ) do implementacji tego standardowego algorytmu to 256 lub 2 8 .

Co to oznacza to, że styl określony z 0 identyfikatorów i nazw klasy 256 będzie nadmiernie jeździć styl określony z zaledwie 1 id. Przetestowałem to z kilkoma skrzypcami:

Tak więc istnieje „system punktowy”, ale nie jest to podstawa 10. Jest to podstawa 256. Oto jak to działa:

(2 8 ) 2 lub 65536 razy liczba identyfikatorów w selektorze
+ (2 8 ) 1 lub 256 razy liczba nazw klas w selektorze
+ (2 8 ) 0 lub 1 razy liczba znaczników- nazwy w selektorze

Nie jest to zbyt praktyczne w przypadku ćwiczeń na zapleczu, aby przekazać koncepcję.
Prawdopodobnie dlatego artykuły na ten temat używają bazy 10.

***** [Opera używa 2 16 (patrz komentarz karlcowa). Niektóre inne silniki selektora używają nieskończoności - w rzeczywistości bez systemu punktowego (patrz komentarz Simona Sapina).]

Aktualizacja, lipiec 2014:
Jak zauważył Blazemonger na początku roku, przeglądarki webkit (chrome, safari) wydają się teraz używać wyższej bazy niż 256. Być może 2 16 , jak Opera? IE i Firefox nadal używają 256.

Faust
źródło
34
Ważne: pamiętaj, że liczba 256 nie znajduje się w specyfikacji . Zatem ta odpowiedź opisuje (wprawdzie użyteczny) szczegół implementacji.
Matt Fenwick
6
Nie tylko 256 nie znajduje się w specyfikacji, jak powiedział @MattFenwick, ale także różni się w zależności od implementacji. W Operze jest najwyraźniej większy. W WeasyPrint i cssselect jest to „nieskończoność”: używam krotki liczb całkowitych zamiast pojedynczej liczby całkowitej.
Simon Sapin,
3
Opera @Faust używa 16 bitów zamiast 8
karlcow
4
Szczerze mówiąc, ta odpowiedź ma bardziej praktyczny opis niż odpowiedź Pekki. Zasadniczo to, co mówi @Matt Fenwick: to, co opisujesz, to praktyczna implementacja specyfikacji. W tym wadliwy, ale nie taki, z którym należy cokolwiek robić, czy to przez autorów, czy wdrażających.
BoltClock
7
256 wydaje się być niewystarczające w obecnych wersjach zestawu webkit (Chrome i Safari), co dodatkowo podkreśla uwagę @ MattFenwick.
Blazemonger,
28

Dobre pytanie.

Nie mam pewności - wszystkie artykuły, które udało mi się znaleźć, omijają przykład wielu klas, np. Tutaj - ale zakładam, że jeśli chodzi o porównanie specyfiki selektora klas z identyfikatorem , klasa jest obliczana za pomocą 15tylko wartość , bez względu na to, jak szczegółowe jest.

To pasuje do mojego doświadczenia w zachowaniu specyficzności.

Jednak musi istnieć zestawienie klas, ponieważ

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o

jest bardziej szczegółowe niż

.o

Jedyne wyjaśnienie, jakie mam, jest takie, że specyfika klas zestawionych jest obliczana tylko względem siebie, ale nie względem identyfikatorów.

Aktualizacja : już w połowie to rozumiem. Nie jest to system punktowy, a informacje o klasach ważących 15 punktów są nieprawidłowe. Jest to 4-częściowy system numeracji bardzo dobrze wyjaśniony tutaj .

Punktem wyjścia są 4 cyfry:

style  id   class element
0,     0,   0,    0

Zgodnie z wyjaśnieniem W3C dotyczącym specyficzności , wartości specyficzności dla powyższych reguł są następujące:

#a            0,1,0,0    = 100
classes       0,0,15,0   = ... see the comments

jest to system numeracji o bardzo dużej (nieokreślonej?) podstawie.

Rozumiem, że ponieważ podstawa jest bardzo duża, żadna liczba w kolumnie 4 nie może przebić liczby> 0 w kolumnie 3, to samo w kolumnie 2, kolumnie 1 .... Czy to prawda?

Byłbym zainteresowany, czy ktoś, kto lepiej zna matematykę niż ja, mógłby wyjaśnić system liczbowy i jak przekonwertować go na dziesiętne, gdy poszczególne elementy są większe niż 9.

Pekka
źródło
Dzieje się tak, ponieważ jest między .o i .a .b itd. Więc będzie traktować je zbiorczo. Ale między identyfikatorem a klasą, np .: .a i #a, identyfikator zawsze będzie dominował. Będzie on (zakładam) liczyć się między klasami tylko wtedy, gdy nie ma atrybutu bardziej przytłaczającego. Np. Klasa przejdzie przez element i id nad klasą.
Sphvn
@Ozaki też to zakładam, ale jest to sprzeczne z tym, co OP mówi o systemie punktów. W grze musi być więcej. Chciałbym zobaczyć zasady, które za tym stoją.
Pekka
Właśnie zdałem sobie sprawę, że oboje doszliśmy do tego samego wniosku. Wspaniała robota!
Sam
5
Jeśli chodzi o matematykę, możemy tutaj pracować na podstawie 16 (ponieważ żadna z poszczególnych liczb nie przekracza 15). Więc 0,1,0,0 = 0100h = 256 0,0,15,0 = 00f0h = 240256> 240, więc selektor id wygrywa.
Matthew Wilson
1
Tak, możesz myśleć o obliczeniach specyficzności jako wykonywanych w systemie liczbowym o dużej podstawie. Myślę, że termin „konkatenacja” (również używany w specyfikacji) jest o wiele lepszym opisem. (Przyszedłem z odpowiedzi na nowe pytanie, które okazuje się być oszustwem tego, idź rysunek ...)
BoltClock
9

Obecna wersja robocza selektorów poziomu 4 dobrze opisuje specyfikę w CSS:

Specyfika porównuje się, porównując kolejno trzy składniki: specyficzność z większą wartością A jest bardziej szczegółowa; jeśli dwie wartości A są ze sobą powiązane, wówczas specyficzność z większą wartością B jest bardziej szczegółowa; jeśli dwie wartości B są również powiązane, wówczas specyficzność z większą wartością c jest bardziej szczegółowa; jeśli wszystkie wartości są takie same, te dwie specyfiki są równe.

Oznacza to, że wartości A, B i C są całkowicie niezależne od siebie.

15 klas nie daje twojemu selektorowi wyniku specyficzności równego 150, daje mu wartość B równą 15. Pojedyncza wartość A wystarczy, aby to pokonać.

Jako metaforę wyobraź sobie rodzinę jednego dziadka, jednego rodzica i jednego dziecka. Można to przedstawić jako 1,1,1 . Jeśli rodzic ma 15 dzieci, nie czyni to nagle kolejnym rodzicem (1, 2, 0 ). Oznacza to, że na rodzicu spoczywa dużo większa odpowiedzialność niż przy jednym dziecku ( 1,1,15 ). ;)

Ta sama dokumentacja mówi dalej:

Ze względu na ograniczenia pamięci, implementacje mogą mieć ograniczenia dotyczące rozmiaru A , B lub c . Jeśli tak, wartości wyższe od limitu muszą być zaciśnięte do tego limitu, a nie przekraczać.

Zostało to dodane, aby rozwiązać problem przedstawiony w odpowiedzi Fausta , zgodnie z którym implementacje CSS w 2012 roku pozwoliły na przepełnienie wartości specyficzności.

W 2012 roku większość przeglądarek zaimplementowała ograniczenie 255, ale to ograniczenie mogło się przepełnić. 255 klas miał A, B, C specyficzności wynik 0,255,0 , ale 256 klas przepełniony i miał A, B, C wynik 1,0,0 . Nagle nasza wartość B stała się naszą wartością A. Dokumentacja Selektorów poziomu 4 całkowicie naświetla ten problem, stwierdzając, że nigdy nie można dopuścić do przekroczenia limitu. Dzięki tej realizacji, zarówno 255 i 256 klas miałby taki sam A, B, C wynik 0,255,0 .

Problem podany w odpowiedzi Fausta został już naprawiony w większości nowoczesnych przeglądarek.

James Donnelly
źródło
8

Obecnie korzystam z książki CSS Mastery: Advanced Web Standards Solutions .

Rozdział 1, strona 16 mówi:

Aby obliczyć, jak konkretna jest reguła, do każdego typu selektora przypisana jest wartość liczbowa. Specyfika reguły jest następnie obliczana poprzez zsumowanie wartości każdego z jej selektorów. Niestety, specyficzność nie jest obliczana na podstawie 10, ale wysoką, nieokreśloną liczbę zasadową. Ma to na celu zapewnienie, że bardzo specyficzny selektor, taki jak selektor identyfikatora, nigdy nie jest zastępowany przez wiele mniej szczegółowych selektorów, takich jak selektory typów.

(podkreślenie moje) i

Specyfika selektora jest podzielona na cztery poziomy składowe: a, b, c i d.

  • jeśli styl jest stylem wbudowanym, a = 1
  • b = całkowita liczba selektorów identyfikatorów
  • c = liczba selektorów klas, pseudoklas i atrybutów
  • d = liczba selektorów typu i selektorów pseudoelementów

Dalej mówi się, że często można wykonać obliczenia w oparciu o podstawę 10, ale tylko wtedy, gdy wszystkie kolumny mają wartości mniejsze niż 10.


W twoich przykładach identyfikatory nie są warte 100 punktów; każdy jest wart [0, 1, 0, 0]punktów. Dlatego jeden identyfikator [0, 1, 0, 0]przewyższa 15 klas, ponieważ jest większy niż [0, 0, 15, 0]w systemie liczb o dużej podstawie.

Matt Fenwick
źródło
4

Bardzo lubię porównywać ranking Specyfika do tabeli medalowej Igrzysk Olimpijskich (metoda najpierw złota - najpierw na podstawie liczby złotych medali, potem srebrnych, a potem brązowych).

Działa również z twoim pytaniem (ogromna liczba selektorów w jednej grupie specyficzności). Specyfika rozpatrywana oddzielnie dla każdej grupy. W prawdziwym świecie bardzo rzadko widziałem przypadek z kilkunastoma selektorami).

Jest też całkiem dobry kalkulator dostępny swoistość tutaj . Możesz umieścić tam swój przykład (#a i .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) i zobaczyć wyniki.

Przykładowa tabela medalowa Igrzysk Olimpijskich w Rio 2016 wygląda jak wprowadź opis obrazu tutaj

rkarczmarczyk
źródło
3

Nie wierzę, że wyjaśnienie na blogu jest poprawne. Specyfikacja jest tutaj:

http://www.w3.org/TR/CSS2/cascade.html#specificity

„Punkty” z selektora klasy nie mogą się sumować, by być ważniejszymi niż selektor „id”. Po prostu tak nie działa.

Matthew Wilson
źródło
Jak powiedziałem w mojej odpowiedzi. ^^ Jednak robi różnicę, jeśli masz więcej tego samego typu (element, klasa, identyfikator). Ale jest to całkiem oczywiste, jeśli 5 mówi, że czerwony, a 3 - niebieski.
Sphvn
Sformułowanie dotyczące specyficzności prawdopodobnie nie zmieniło się zbytnio między CSS2 i CSS2.1, ale naprawdę powinieneś wskazywać na specyfikację CSS2.1 w przyszłych dyskusjach, ponieważ całkowicie zastępuje CSS2, który był ogólnie zepsuty w momencie wydania.
Robin Whittleton,
1

Powiedziałbym to:

Element < Class < ID

Myślę, że stosują się tylko w zależności od tego, co otrzymujesz, jeśli jest to wielokrotność tego samego. Tak więc klasa zawsze przesłoni element i identyfikator zawsze nad klasą, ale jeśli zależy to od tego, do którego z 4 elementów, gdzie 3 jest za niebieskie, a 1 za czerwone, będzie niebieskie.

Na przykład:

.a .b .c .d .e .f .g .h .i .j .k .l
{
color: red;
}

 .m .n .o
{
color blue;
}

Powinien stać się czerwony.

Zobacz przykład http://jsfiddle.net/RWFWq/

„Jeśli w 5 napisach jest czerwony, a 3 na niebiesko, to zrobię się czerwony”

Sphvn
źródło