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

Przydatny selektor

Mowa tutaj o uniwersalnym selektorze jakim jest gwiazdka. Przykład użycia:

*
{
    margin: 0px;
}

Powoduje on, że wszystkie elementy występujące w dokumencie będą miały zerowe marginesy. Używam go, gdy chcę zapanować nad wszystkimi elementami i nie mieć nieoczekiwanych różnic w odstępach między przeglądarkami.

Przykładowo elementy takie jak paragraf czy formularz same dodają sobie odstępy. Selektor może również zawierać ustawienia dotyczące czcionki, ramek itp. Oczywiście kolejnymi stylami można nadawać dowolne odstępy na dowolnych elementach i tym samym nadpisać ustawienia dokonane tym selektorem.

Działa tylko pod Operą

Jak uzyskać kod postaci:

<div id="title">Tytuł jakiś</div>

za pomocą CSS? Jest na to ciekawy sposób, który działa niestety tylko pod Operą – mam wersję 9.23. Pod IE6 i FF 2.0.0.8 niestety nie:( Ale wracając do sposobu, to można to zrobić następująco:

<div id="title"></div>

Jak widać, pozbyłam się tekstu, który znajdował się w divie.
Zamiast tego włożę go do… stylu:)

#title
{
    content:Tytuł jakiś
}

We wspomnianej już Operze wyświetlone zostanie na ekranie po prostu Tytuł jakiś. Jednym słowem div o id #title zostanie wypełniony tekstem podanym we właściwości content:)

Coś zamiast float

Załóżmy, że chcemy zrobić kilka list w kilku kolumnach. Pierwsza rzecz jaka przychodzi do głowy, to nadanie im parametru float i po sprawie. Jednak można to też zrobić nie używając float. Przykład:

  • Element 1 listy numer 1
  • Element 2 listy numer 1
  • Element 3 listy numer 1
  • Element 1 listy numer 2
  • Element 2 listy numer 2
  • Element 3 listy numer 2

W powyższym przypadku nie użyłam float:)
Styl jaki nałożony został na pierwszą kolumnę, to:

margin: 0px;
padding: 0px;
list-style-type: none;

Natomiast na drugą:

margin: -77px 0px 0px 170px;
padding: 0px;
list-style-type: none;

Jak widać nie użyłam float. Zamiast float pojawia się w przypadku drugiej kolumny odpowiednio skonstruowana wartość margin. Mianowicie ujemna wartość (-62 piksele) powoduje że element objęty tym stylem zostanie podniesiony do góry – dzięki czemu wyrówna się z kolumną lewą. Natomiast ostatnia wartość (170 pikseli) to odsunięcie od lewej strony – odpowiednie by kolumny na siebie nie nachodziły.
Oczywiście można te dwie kolumny utworzyć używając właściwości „float” ustawianej na left bądź right w zależności od potrzeb.

position: fixed

Zauważyłam, że choć działanie tej CSS-owej właściwości różni się efektami w Firefoxie, Operze i Internet Explorerze(w FF i O działa, ale w IE 6 nie bardzo) dla elementów DIV, to dla elementu BODY działa bez problemu pod wszystkim:) Na niewiele się to przyda, jeśli ktoś koniecznie chce zrobić DIV z tłem fixed, ale lepsze to niż nic:)