Siła selektorów

Dlaczego styl nie nadpisje innego stylu mimo tego, że jego deklaracja jest później w kodzie?

Często w przypadku CSS nie chodzi tylko o kolejność ale też o siłę selektorów.

Testowanie siły selektorów

Dla poniższego kodu zastosuję reguły CSS, które będą odnosiły się do elementu em.

<div id="test">
	<div id="test_a" class="test_b">
		<div id="test_c">
			<p>
				<span class="test_d">
					<strong>
						<em>
							To jest testowy tekst!
						</em>
					</strong>
					A to już nie jest!
				</span>
			</p>
		</div>
	</div>
</div>

Teraz pierwszy kod css. Obie deklaracje wskazują na ten sam element. Różnica między nimi polega na tym, że w drugim przypadku do jednego z elementów odnoszę się po id a nie po klasie. Jaki kolor będzie miał tekst w elemencie strong?

#test div.test_b div#test_c p span.test_d strong em{color:red;}
#test div#test_a div#test_c p span.test_d strong em{color:green;}

Jesli odpowiedziałeś, że zielony to powiedziałeś dobrze. Tekst będzie zielony, co widać na testowym elemencie:

To jest testowy tekst! A to już nie jest!

W tym przypadku mamy dokładnie te same deklaracje css tylko zamienione miejscami. Jaki kolor będzie miał tekst w elemencie strong?

#test div#test_a div#test_c p span.test_d strong em{color:green;}
#test div.test_b div#test_c p span.test_d strong em{color:red;}

Większosć osób odpowie, że czerwony, bo deklaracja ustawiająca kolor na czerwony "nadpisuje" ta ustawiajacą kolor na zielony ponieważ jest po niej. Prawidłowa odpowiedź to też zielony. Kolejność deklaracji CSS nie ma znaczenia chyba, że deklaracje są jednakowo silne. Opisze w skrócie jak to działa w tym przykładzie. Po więcej informacji odsyłam do tekstu Calculating a selector's specificity.

Siła selektorów obliczana jest poprzez połączenie w jedną liczbę następujących sum: [suma selektorów id], [suma selektorów klas, pseudoklas i atrybutów], [suma selektorów elementów].

Przykładowo dla kodu:

#test div#test_a div#test_c p span.test_d strong em{color:green;}

są trzy selektory id: #test, #test_a, #test_c; jeden selektor klasy: .test_d; sześć selktorów elementów: div, div, p, span, strong, em; siła całości wynosi zatem 3, 1, 6 = 316.

Dla reguł omawianych w tym przykładzie jest to odpowiednio 3, 1, 6 = 316 i 2, 2, 6 = 226 więc widać, że pierwsza reguła jest silniejsza od drugiej co potwierdza przykładowy element:

To jest testowy tekst! A to już nie jest!

I na potwierdzenie tego przykład krótkiego selektora i długiego:

#test #test_c strong em{color:green;}
#test div.test_b div p span.test_d strong em{color:red;}

Krótszy ma siłę 2, 0, 2 = 202 a dłuższy 1, 2, 6 = 126 więc tekst znów będzie zielony:

To jest testowy tekst! A to już nie jest!

Jeszcze dodatkowo zagadka. Jakie kolor tekst będzie miał teraz przy takich deklaracjach

#test # test_a #test_c strong {color:green;}
#test div.test_b div p span.test_d strong em{color:red;}

Pierwszza deklaracja ma siłę 3,0,1 = 301, natomiast druga 1,2,6=126 ale tekst i tak będzie czerwony. Dlaczego? Bo pierwsza deklaracja wskazuje na element strong. Druga wskazuje na element em, który jest wewnątrz strong więc momo iż ta deklaracja jest słabsza to jest ona jednak dokładniejsza i dlatego nadpisze pierwszą.

To jest testowy tekst! A to już nie jest!

That's all folks!