Stopień ważności selektorów CSS

W poprzednich częściach kursu CSS dowiedzieliśmy się w jaki sposób reguły CSS łączą się ze sobą. Dowiedzieliśmy się również w jaki sposób właściwości CSS nadpisują się, w przypadku gdy w kodzie HTML znajduje się więcej reguł CSS odnoszących się do tego samego elementu HTML oraz posiadających te same właściwości CSS o różnych wartościach. Wspomniane zagadnienia były w miarę proste do zrozumienia, ponieważ reguły CSS były zbudowane z tej samej liczby selektorów CSS, o tym samym stopniu ważności.

W tej części kursu CSS zapoznamy się z regułami CSS zbudowanymi z większej liczby selektorów o różnych stopniach ważności.

Aby zrozumieć stopień ważności selektorów CSS musimy znać grupy ważności na jakie dzielą się selektory CSS, ponieważ każda taka grupa posiada swój własny stopień ważności.

Wspomniane grupy ważności możemy określić za pomocą pomocniczych oznaczeń, np. G1, G2, G3.

G1 - najwyższy stopień ważności
Do tej grupy selektorów CSS należy tylko jeden selektor, a jest nim selektor identyfikatora, np. #moj_p
G2 - średni stopień ważności
Do tej grupy selektorów CSS należą selektory atrybutu, selektory pseudoklasy oraz selektor klasy, np. .moj_p
G3 - najniższy stopień ważności
Do tej grupy selektorów CSS należą selektory pseudoelementu oraz selektor elementu, np. p
Znaki niewpływające na stopień ważności
Następujące znaki, nie wpływają na stopień ważności selektorów CSS: *, ,, >, +, ~ oraz spacja, która określa selektor potomka

Gdy utworzymy kilka reguł CSS, które będą posiadały te sama właściwości CSS i które będą odnosiły się do tego samego elementu HTML, oraz które będą zbudowane z różnych typów selektorów CSS, to przeglądarka internetowa dokona selekcji właściwości CSS, przeznaczonych dla danego elementu HTML, na podstawie stopnia ważności selektorów danej reguły CSS.

To tyle, jeżeli chodzi o dość zawiłe zależności. Czas na trochę praktyki.

Przyjrzyjmy się następującemu dokumentowi HTML, a raczej spójrzmy na kod HTML, jaki został w nim umieszczony:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Darmowy Kurs CSS</title>

    <style>
      p {
        background-color:lightblue;
        padding:15px;
        border:1px solid black;
      }

      #moj_p {
        background-color:gold;
      }
    </style>
  </head>

  <body>

    <div id="moj_div">
      <p id="moj_p" class="moj_p">to jest przykładowy element - p</p>
    </div>

  </body>
</html>

Na podstawie informacji, jakie do tej pory zostały przedstawione w poprzednich częściach kursu CSS, możemy wywnioskować, że po wyświetleniu danego dokumentu HTML, w oknie przeglądarki internetowej, ujrzymy element p, który będzie posiadał w sobie marginesy wewnętrzne padding oraz obramowanie border, jak również kolor tła background-color.

to jest przykładowy element - p

Kolor tła elementu p będzie złoty, jednak nie dlatego że reguła utworzona za pomocą selektora #moj_p znajduje się po regule utworzonej za pomocą selektora p, a dlatego że selektor #moj_p ma wyższy stopień ważności od selektora p.

Spójrzmy jak będzie wyglądał nasz przykładowy element p, gdy zmienimy kolejność reguł CSS w naszym kodzie HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Darmowy Kurs CSS</title>

    <style>
      #moj_p {
        background-color:gold;
      }

      p {
        background-color:lightblue;
        padding:15px;
        border:1px solid black;
      }
    </style>
  </head>

  <body>

    <div id="moj_div">
      <p id="moj_p" class="moj_p">to jest przykładowy element - p</p>
    </div>

  </body>
</html>

Rezultat:

to jest przykładowy element - p

Rezultat jest taki sam jak w poprzednim przykładzie, mimo że reguła CSS utworzona za pomocą selektora p została umieszczona po regule CSS, która została utworzona za pomocą selektora #moj_p.

Mogłoby się nam wydawać, że kolor tła elementu p będzie jasnoniebieski (lightblue), jednak wcale tak nie jest, ponieważ jest on złoty (gold), a więc reguła CSS utworzona za pomocą selektora p oraz posiadająca w sobie, między innymi właściwość background-color:lightblue; nie nadpisała właściwości background-color:gold; która została umieszczona w regule CSS utworzonej za pomocą selektora #moj_p.

Dlaczego tak się dzieje?

Ponieważ przeglądarka internetowa "widząc", że kilka reguł CSS, które posiadają te same właściwości CSS (w naszym przykładzie tą właściwością jest właściwość background-color), oraz które odnoszą się do tego samego elementu HTML (w naszym przykładzie tym elementem jest element p), dokonuje ona selekcji na podstawie stopnia ważności danej reguły CSS. Stopień ważności reguły CSS jest uzależniony od stopnia ważności selektorów CSS, które tworzą daną regułę CSS.

Właściwości CSS użyte w regułach CSS, które zostały utworzone za pomocą selektorów CSS, które posiadają niższy stopień ważności, nie mogą nadpisać tych samych właściwości CSS, które zostały użyte w regułach CSS utworzonych za pomocą selektorów o wyższym stopniu ważności. W tym wypadku nie ma znaczenia, w jakiej kolejności umieściliśmy nasze reguły CSS, w kodzie HTML, czy też w kodzie osobnego pliku CSS.

W naszym przykładzie występują dwie reguły CSS. Pierwsza z nich, czyli #moj_p, została utworzona za pomocą selektora identyfikatora, który należy do grupy G1, a więc posiada w sobie najwyższy stopień ważności. Natomiast druga reguła CSS, czyli p, została utworzona za pomocą selektora elementu, który należy do grupy G3, a więc posiada w sobie najniższy stopień ważności. Dlatego też reguła CSS utworzona za pomocą selektora p nie może nadpisać właściwości CSS występujących w regule CSS, która została utworzona za pomocą selektora #moj_p.

Spójrzmy teraz na nieco inną sytuację w naszym dokumencie HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Darmowy Kurs CSS</title>

    <style>
      p#moj_p {
        background-color:gold;
      }

      #moj_p {
        background-color:lightblue;
        padding:15px;
        border:1px solid black;
      }
    </style>
  </head>

  <body>

    <div id="moj_div">
      <p id="moj_p" class="moj_p">to jest przykładowy element - p</p>
    </div>

  </body>
</html>

Rezultat:

to jest przykładowy element - p

Kolor tła w elemencie p jest złoty (gold), a nie jasnoniebieski (lightblue). Tym razem nasze reguły CSS zostały utworzone za pomocą selektora p#moj_p oraz #moj_p.

Przeglądarka "widząc", że w naszym kodzie znajdują się reguły CSS odnoszące się do tego samego elementu HTML, zacznie ona sprawdzać stopień ważności danych reguł CSS, na podstawie stopnia ważności ich selektorów CSS.

W pierwszej kolejności zostanie podjęta próba sprawdzenia czy w regułach CSS został użyty selektor identyfikatora, który posiada najwyższy stopień ważności, ponieważ należy on do grupy G1.

W naszym przykładzie obie reguły CSS posiadają wspomniany selektor identyfikatora (jest to #moj_p), w tej samej liczbie (po jednym dla każdej reguły CSS), dlatego przeglądarka internetowa w tym momencie nie będzie mogła określić, tylko na podstawie selektora CSS należącego do grupy G1, która reguła CSS jest bardziej ważna.

W następnej kolejności zostanie podjęta próba sprawdzenia czy w regułach CSS został użyty jakiś selektor, który posiada średni stopień ważności, a więc taki, który należy do grupy G2.

W naszym przykładzie obie reguły CSS nie posiadają w sobie selektorów należących do grupy G2, dlatego przeglądarka internetowa w tym momencie nie będzie mogła określić, która reguła CSS jest bardziej ważna.

W następnej kolejności zostanie podjęta próba sprawdzenia czy w regułach CSS został użyty jakiś selektor, który posiada najniższy stopień ważności, a więc taki, który należy do grupy G3.

W naszym przykładzie reguła p#moj_p posiada w sobie selektor elementu (jest to p), który należy do grupy G3, dlatego to właśnie reguła p#moj_p będzie bardziej "ważną" regułą CSS, a nie reguła #moj_p.

A o to nieco inna sytuacja:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Darmowy Kurs CSS</title>

    <style>
      p#moj_p {
        background-color:gold;
      }

      #moj_p.moj_p {
        background-color:lightblue;
        padding:15px;
        border:1px solid black;
      }
    </style>
  </head>

  <body>

    <div id="moj_div">
      <p id="moj_p" class="moj_p">to jest przykładowy element - p</p>
    </div>

  </body>
</html>

Rezultat:

to jest przykładowy element - p

Tym razem bardziej ważną regułą CSS będzie reguła #moj_p.moj_p, a nie reguła p#moj_p, ponieważ obie reguły CSS posiadają w sobie tą samą liczbę selektorów identyfikatora, lecz reguła #moj_p.moj_p jest dodatkowo zbudowana za pomocą selektora klasy (czyli .moj_p), który należy do grupy G2, natomiast reguła p#moj_p nie posiada w sobie żadnego selektora należącego do grupy G2 i właśnie dlatego kolor tła elementu p jest jasnoniebieski (lightblue), a nie złoty (gold).

Następny przykład:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Darmowy Kurs CSS</title>

    <style>
      #moj_div > #moj_p {
        background-color:lightblue;
        padding:15px;
        border:1px solid black;
      }

      p#moj_p.moj_p:first-child {
        background-color:gold;
      }
    </style>
  </head>

  <body>

    <div id="moj_div">
      <p id="moj_p" class="moj_p">to jest przykładowy element - p</p>
    </div>

  </body>
</html>

Rezultat:

to jest przykładowy element - p

Tym razem w dość łatwy sposób możemy określić, która reguła CSS jest bardziej ważna. Bardziej ważną regułą CSS będzie reguła #moj_div > #moj_p, ponieważ jest ona zbudowana z dwóch selektorów identyfikatora (czyli #moj_div oraz #moj_p), które należą do grupy G1, natomiast reguła p#moj_p.moj_p:first-child jest zbudowana tylko z jednego selektora identyfikatora (czyli #moj_p), który należy do grupy G1.

Uwaga Jeżeli reguły CSS odnoszące się do tego samego elementu HTML były by zbudowane w tej samej liczbie z selektorów należących do grupy: G1, G2 lub G3, to ważniejszą regułą CSS będzie ta reguła, która została umieszczona "niżej" w kodzie HTML.

Przykład:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Darmowy Kurs CSS</title>

    <style>
      /* G1 - #moj_div, G2 - .moj_p, G3 - p */
      #moj_div > p.moj_p {
        background-color:lightblue;
        padding:15px;
        border:1px solid black;
      }

      /* G1 - #moj_p, G2 - :first-child, G3 - p */
      p#moj_p:first-child {
        background-color:gold;
      }
    </style>
  </head>

  <body>

    <div id="moj_div">
      <p id="moj_p" class="moj_p">to jest przykładowy element - p</p>
    </div>

  </body>
</html>

Rezultat:

to jest przykładowy element - p

W kolejnej części kursu CSS poznamy do czego służy deklaracja !important, dzięki której będziemy mogli "łamać" zasady, które do tej pory poznaliśmy.