Kiedy mamy problem z CSSami…

Każdy z nas czasem patrzy na swój plik css oraz na strukturę htmla swojej strony i zastanawia się dlaczego ten tekst jest zielony, chociaż w cssie wyraźnie widnieje, że ma być czerwony i do tego podkreślony… W prostych cssach łatwo błąd znaleźć i naprawić. W bardziej skomplikowanych może nam to przysporzyć sporo straconego czasu i nerwów;)
Niedawno znalazłam coś, co może sprawić, że już nigdy więcej nie będę się zastanawiać „dlaczego to nie działa”;) Co prawda takich sytuacji nie miewam wiele, ale ich całkowite wyeliminowanie nie zaszkodzi:)
Lekarstwem na te problemy ma być tzw. CSS Specificity czyli jeśli upieramy się przy tłumaczeniu na język ojczysty – Specyficzność CSS, a dokładniej sposób w jaki reguły zapisane przez nas w cssach są realizowane przez przeglądarki.
Pierwsza rzecz, na której wszystko się opiera, to fakt iż poszczególne selektory mają przyporządkowane pewne wagi. Wagi te przedstawiają się następująco:

  • największą wagę (1000) mają selektory znajdujące się jako atrybut we właściwości style danego elementu, np.:
    <span style="color: green;">Zielony tekst</span>
  • kolejne (waga 100) są identyfikatory elementów, np.:
    #kontener
    {
        background-color:yellow;
    }
  • następne w kolejce (waga 10) są nazwy klas, atrybutów i pseudoklas, np.
    .zielona_klasa
    {
        color: green;
    }
    a:link
    {
        text-decoration:underline;
    }
  • Ostatnie, najmniej liczące się (dosłownie;) – waga 1) to elementy i pseudoelementy, np.:
    <img alt="" />
    :after

Dla lepszego zrozumienia przejrzyjmy parę przykładów obliczania specificity:

  1. #left_column div
    {
        border: solid 1px;
    }

    Mamy tutaj jeden identyfikator (100) i jeden element (1), co w sumie (100+1) daje nam specificity na poziomie 101.

  2. Weźmy przykład cssów które nieraz potrafią nieźle namieszać. Mianowicie jeśli z jakiś przyczyn część definicji mamy w zewnętrznym pliku css, a część inline w kodzie HTML. Przykładowo, w cssie mamy coś takiego:
    #menu
    {
       border:solid 1px;
       background-color: green;
    }

    natomiast w pliku html coś takiego:

    <div id="menu" style="background-color: blue">[tutaj menu bedzie]</div>

    Mamy więc 1000 za styl inline oraz 100 za identyfikator. Co w sumie daje 1100.

W ostatnim przykładzie nasuwa się nam pewna kwestia. Mianowicie jakiego koloru w efekcie będzie tło tego menu? Niebieskie czy zielone?
Odpowiedź brzmi niebieskie. Powodem tego jest kolejna rzecz odgrywająca ważną rolę w specificity – jedne elementy są ważniejsze niż inne. I tak kiedy mamy style zdefiniowane inline, nadpisują one wszystkie inne poprzedzające je (czy to zawarte w identyfikatorach, czy klasach czy elementach). W kwestii dalszej hierarchii: style zdefiniowane w identyfikatorach są ważniejsze niż style zdefiniowane w klasach, a te z kolei są ważniejsze niż te zdefiniowane w elementach. Oto prosta ilustracja:

/*** domyślnie tło dokumentu będzie białe a wszystkie czcionki ustawiamy na Verdanę w rozmiarze 10px ***/
body
{
    font-size: 10px;
    font-family: Verdana;
    background-color: #FFF;
}
/*** jednak chcielibyśmy, żeby header naszej strony był wyróżniony odpowiednią czcionką ***/
#h1
{
    font-size: 19px;
    font-weight: bold;
}
/*** niektóre elementy będą dodatkowo pisane kursywą ***/
.italic
{
    font-weight: normal;
    font-style: italic;
}
<h1>Tekst headera</h1>
<div class="italic" style="background-color: yellow">Jakiś tekst pisany kursywą</div></h1>

Co się z tym stanie?
Dokument wstępnie miał ustawione tło na białe, czcionkę na Verdanę w rozmiarze 10px. Jednak już na wstępie, gdy pojawia się header (h1) zmienia się rozmiar czcionki oraz zostaje ona pogrubiona. Tak więc style identyfikatora nadpisały style elementu. Z kolei div znajdujący się w headerze ma przypisany styl inline, który zmienia tło tegoż elementu nadpisując kolejną właściwość ustawioną w body. Ktoś jeszcze mógłby się zastanawiać… przecież Verdana 10 i białe tło zostały ustawiona na elemencie body, a nie div. Przypominam o dziedziczeniu:) W końcu to cascading style sheets. Jeśli nie ustawimy inaczej to styl przypisany naszemu divowi jest identyczny jak ten, który został nadany body, ponieważ body jest przodkiem diva;)
Parę rzeczy o których warto pamiętać jeśli chodzi o specificity:

  • jeśli dany element definiują różne grupy selektorów to ta, która ma większą specificity zadziała
  • jeśli te grupy selektorów mają tą samą specificity, wówczas zadziała ta która została zdefiniowana jako ostatnia

I jeszcze link do kalkulatora specificity – Kalkulator