Siemano! Obejrzałem najnowszy odcinek GoT, więc czas na kreatywną pracę z tekstem!

Ostatnio w pracy dużo siedzę przy front-endzie. Co prawda I don’t speak JavaScript, ale front-end to nie tylko skrypty. Osobiście dużo więcej frajdy sprawia mi pisanie deklaratywnie w HTMLu i CSSach. Bardzo długo do tematu programowania w HTMLu podchodziłem drwiąco. Musicie jednak wiedzieć, że opisanie wyglądu i zachowania strony to nie lada wyczyn. Podział strony na sensowne częsci w HTMLu jest względnie prosty (w końcu wstawiamy tam dane, helloooo). Dużym problemem są za to style, które nakładają się na siebie w często mało oczywisty sposób. W dzisiejszym wpisie przybliżę więc temat podziału CSSów na moduły.

CSS, czyli jak bardzo przegrałeś

W ramach przypomnienia jak w ogóle wygląda CSS, zapisałem przykładową regułę:

selector {
    property: value;
    another-property: value2;
}

Selektory odpowiadają za wybór elementów, na które zostaną nałożone style. Możliwy jest wybór elementów strony przy pomocy tagów HTML, id lub klas. Możliwe jest również łączenie selektorów w celu uszczegółowienia tego, co ma zostać ostylowane, np. można ostylować wszystkie elementy p, będące potomkami elementu article:

article p {
    background-color: pink;
}

Właściwości (ang. property) i wartości (ang. value) odpowiadają za zmianę wyglądu lub zachowania wybranych elementów. W powyższym przykładzie, wszystkie elementy p, będące potomkami article będą miały różowe tło.

Albo nie wszystkie… Pisiont na pisiont. CSS jest wyposażony w mechanizm rozwiązywania konfliktów wg. specyficzności (ang. specificity). Wygrywa selektor najsilniejszy, a więc taki, którego specyficzność jest najwyższa. Specyficzność zależy od rodzaju selektora, jego złożoności i prawdopodobnie od promieniowania kosmicznego oraz liczby Yeti w promieniu 6 mil. Chociaż co do dwóch pierwszych nie jestem pewien. Reguła kciuka jest następująca: im bardziej zakręcony selektor, tym wyższa specyficzność. Prosty przykład wrzuciłem na JSFiddle:

Problem z CSSem zaczyna się w momencie, w którym struktura strony staje się skomplikowana i należy zdecydować, od którego elementu drzewa będziemy zaczynali selektor.

Jak wyznaczyć korzeń selektora?

Problem da się zauważyć już w podlinkowanym wcześniej przykładzie. Zacząłem selektor od elementu article. Czy na pewno był on wymagany? Albo był, albo nie był. Wszystko zależy tak naprawdę od kontekstu. Podejmując decyzję o korzeniu hierarchii selektora, zadaję sobie następujące pytania:

  • Czy elementy p wystąpią w przyszłości poza artykułem?
  • Czy elementy p poza artykułem powinny mieć nałożone te same style?
  • Czy wszystkie elementy p w artykule powinny mieć nadany określony styl? (Może warto uszczegółowić selektor?)
  • Czy article jest odrębnym komponentem?

Ogólna zasada jest następująca: wybierz najmniej szczegółowy selektor, który spełni wszystkie wymagania. Stosując zbyt skomplikowane selektory prosisz się o problemy ze specyficznością w przypadku nadpisywania stylu.

LESS, czyli zagnieżdżenia, zmienne i funkcje w stylach

Skoro już jesteśmy przy skomplikowanych selektorach, chciałbym pokazać Ci jedno z narzędzi ułatwiających pracę z bardzo złożonymi arkuszami stylów. Jest nim LESS. LESS jest nadzbiorem języka CSS. Oznacza to tyle, że każdy CSS jest poprawnym kodem LESS, dzięki czemu możesz stopniowo przepisywać style na LESS.

Zagnieżdżenia

LESS pozwala na zagnieżdżanie selektorów. Oznacza to, że przykładowy CSS można przepisać na poniższą postać:

article {
    p {
        color: pink;

        &.black-as-hell {
            color: black;
        }
    }

    *:last-child {
        color: green;
     }
}

Każdy poziom zagnieżdżenia oznacza kolejną składową selektora. Jeżeli chcemy uzyskać składową selektora złożoną np. z taga i klasy, należy skorzystać z operatora &.

Zmienne

Bardzo często projekt strony przewiduje wykorzystywanie jednego koloru w wielu miejscach. To samo może dotyczyć np. marginesów oraz czcionek. W takiej sytuacji LESS oferuje nam zmienne.

@paragraph-color: pink;
@alternative-paragraph-color: black;
@last-element-color: green;

article {
    p {
        color: @paragraph-color;

        &.black-as-hell {
            color: @alternative-paragraph-color;
        }
    }

    *:last-child {
        color: @last-element-color;
     }
}

Ważne jest, aby nazwy zmiennych powiązane były ze znaczeniem elementów, do których będą wykorzystywane. Nazwanie zmiennej @black nie da nam żadnego zysku – zmodyfikowanie jej zawartości zmusi nas do zmiany jej nazwy.

Mixiny i funkcje

Język LESS oferuje możliwość definiowania parametryzowanych reguł. Taka reguła nosi nazwę mixin.

.apply-color(@color) {
    color: @color;
}

Mixiny mają raczej ograniczone zastosowania, jednak są sytuacje, w których znacznie ułatwiają życie. Przykładem może być nadanie elementowi clearfixa:

.clearfix() {
    zoom: 1;

    &:before,
    &:after {
        content: "";
        display: table;
    }

    &:after {
        clear:  both;
    }
}

.floating-elements-container {
    .clearfix();
}

LESS oferuje również zbiór wbudowanych funkcji, pozwalających na manipulowanie wartościami. Możliwe jest np. przyciemnienie koloru, nadanie przezroczystości lub wybranie mniejszej wartości (funkcja min).

Podział stylów na wiele plików

Została nam najistotniejsza część naszej wędrówki przez krainę LESSa. Mając odpowiednio wydzielone moduły, wyodrębnione zmienne i mixiny, jesteśmy w stanie podzielić style na wiele plików. Osobiście stosuję następujące zasady:

  • zmienne trafiają do variables.less,
  • mixiny trafiają do mixins.less,
  • każdy moduł trafia do osobnego pliku i załącza referencje do zmiennych i mixinów (za pomocą @import (reference) “variables.less”),
  • jeżeli aplikacja posiada dużo stylów dla urządzeń mobilnych, trafiają one do osobnych plików, np. nazwa-modulu.lg.less, nazwa-modulu.md.less etc.
  • jeżeli style mobilne stanowią nie więcej niż 50 linii kodu, umieszczam je w plikach opisanych szerokością ekranu, np. lg.less, md.less.

Wady i alternatywy

Język LESS zawiera jeden haczyk - przeglądarki go nie interpretują. W związku z tym, należy zbudować go do CSSa po stronie serwera. Obecnie nie stanowi to dużego problemu. Web Essentials dla Visual Studio posiada narzędzie do budowania LESSa. Takie możliwości posiadają również pluginy do Gulpa i Grunta.

Istnieje jedna realna alternatywa dla LESSa, a mianowicie język SASS. Oba języki posiadają porównywalne możliwości. Osobiście korzystam z LESSa, ponieważ był on dużo popularniejszy w świecie .NET gdy zaczynałem swoją przygodę z web developmentem. Siła nawyku :-)

Używasz LESSa w swoich projektach? A może masz inny sposób radzenia sobie z chaosem w arkuszach stylów? Podziel się w komentarzach!