Porządkowanie kodu CSS - okładka

Porządkowanie kodu CSS

Opublikowano Kategorie Czysty kod, FrontendCzas czytania 8min

Na samym początku swojej przygody z tworzeniem stron WWW zupełnie nie zwracałem uwagi na porządkowanie kodu CSS. Tworzony przeze mnie kod zwykle zawierał się w jednym, spuchniętym pliku CSS. Nazwy klas co prawda
(zwykle) opisywały czym dany element, jest jednak brakowało im systematyczności. Po powrocie do takiego kodu miałem bardzo dużo momentów, gdy nie wiedziałem, czy np. klasa page-header odpowiada za nagłówek całej strony, czy też za np. nagłówek artykułu.

Przykład złego kodu

Zapoznaj się z następującym fragmentem kodu SCSS (wykorzystałem tu jedynie zagnieżdżenia).


.name-item
{
    height: 100%;
}
.name-item > h1 > small
{
    display: block;
    text-align: center;
    padding-bottom: 9vmin;
    padding-top: 1vmin;
    color: rgba(0,0,0,0.4);
    font-size: 3vmin;
}
.projects-container
{
    img
    {
        padding:3vmin;
        transition:0.4s all;
    }
    img:hover {
        transform: scale( 0.9 );
    }
}
.text-justify
{
    box-sizing:border-box;
    font-size: 1.6vmax;
}
.blog
{
    font-size:2rem;
    color:#4d4646;
}

Zobaczmy teraz, co z tym kodem jest nie tak:

  • przede wszystkim złe i mylące są nazwy klas. Nazwy takie jak name-item, czy blog  nie mówią nam absolutnie NIC o stylowanym elemencie. Czy te elementy to są kontenery, nagłówki czy może bloki tekstu? Nie wiadomo;
  • nazwa jest jeszcze bardziej myląca w przypadku klasy text-justify – sugeruje wyjustowanie tekstu. Problem leży w tym, że klasa nie justuje tekstu. Co gorsza, owa klasa nakłada inne style;
  • Moją uwagę zwróciła też klasa projects-container. Nie chodzi tu o samą nazwę, lecz o zagnieżdżony w niej element. Wnioskując po nazwie, jest to jakiś kontener zawierający projekty. Zapewne jest to lista projektów, którym towarzyszy jakieś zdjęcie. Zakładając, że w stylowanym kontenerze są tylko miniaturki projektów, to fragment kodu jeszcze jest akceptowalny.
    Wyobraźmy sobie jednak sytuację, gdy zechcemy umieścić pomiędzy naszymi projektami banery reklamowe będące zdjęciami. W tym momencie dodane banery przyjmą style miniaturek. Czy chcemy, aby baner reklamowy zachowywał się podczas najechania kursorem tak jak miniaturka? Ja bym nie chciał. Problem w tym miejscu można rozwiązać poprzez dodanie klasy np. project-thumbnail na miniaturę projektu;
  • staram się również unikać stylowania po idelementach, a przy stylowaniu korzystać głównie z klas. Aczkolwiek wydaje mi się, że jest to głównie moje widzimisię. Główny powód mojej decyzji poznasz w dalszej części artykułu;
  • kolejnym punktem, gdzie brakuje spójności, jest kolorystyka. Nie chodzi tu jednak o zły dobór kolorów, a o ich zapis. Wykorzystano tu dwa różne sposoby na zapis koloru: #4d4646 oraz rgba(0,0,0,0.4). Starajmy się trzymać jednego formatu. Dodatkowo owe wartości można wyciągnąć i przypisać do zmiennych, które oczywiście również powinny mieć spójne i deskryptywne nazwy. Zmienne są już wspierane nie tylko przez preprocesory, ale i przez natywny CSS, więc nie widzę żadnych przeciwwskazań do ich używania;
  • ostatnim punktem, który zwrócił moją uwagę, jest po raz kolejny klasa text-justify. Osobiście nie jestem zwolennikiem klas, których jedynym zadaniem jest nałożenie stylu. Mam tu na myśli klasy pokroju: font-bold czy align-center. Jednak możemy spotkać się z tego typu klasami, chociażby w bibliotekach np. Bootstrap, a samo podejście do tego typu klas jest moją subiektywną opinią i jak widać, nie każdy się z nią zgadza. Decyzję pozostawiam Tobie 🙂

Porządkowanie kodu CSS - specificity

Specificity

Mając już przykład złego kodu, zastanówmy się, co możemy zrobić, aby nasz kod wyglądał i działał lepiej. Pierwszym terminem, jaki warto poznać, aby tworzyć lepszy i bardziej czytelny kod CSS jest specificity. Intuicyjnie tłumaczę sobie termin ten w ten sposób, że określamy specyficzność danego elementu. Najbardziej specyficzne elementy można wskazać za pomocą id. Element z danym id na danej stronie powinien znajdować się dokładnie JEDEN. Dzięki temu z chirurgiczną precyzją jesteśmy w stanie go ostylować. Następnie w hierarchii mamy klasy, a na końcu elementy.

Specificity jesteśmy w stanie dokładnie obliczyć za pomocą licznych kalkulatorów online. Przeanalizuj poniższy fragment kodu.


<style>
  #square {
    background-color: black;
  }
  
  .square {
    background-color: pink;
  }
  
  div {
    width: 100px;
    height: 100px;
    background-color: orange;
  }
  
</style>

<div class="square" id="square" style="background-color: purple;"> </div>

Wklejając ten kod do pliku HTML i uruchamiając plik w przeglądarce, otrzymamy kwadrat w kolorze… fioletowym. Jest to oczywiście spowodowane stylem inline na elemencie. Starajmy się unikać takich zabiegów. Sam stosuję style inline w bardzo rzadkich i wyjątkowych sytuacjach.

Skupmy się teraz na kodzie w znaczniku <style>. Gdy usuniemy style inline, to kwadrat otrzyma kolor czarny. Ktoś mógłby zapytać dlaczego? Odpowiedzią jest właśnie specificity. Stylowanie po id ma wyższy priorytet niż stylowanie po klasach czy elementach, przez co, mimo że późniejszy kod CSS definiuje inny kolor kwadratu, to kolor się nie zmienia. Gdybyśmy z przykładu usunęli style dla #square to otrzymamy kwadrat w kolorze różowym, ponieważ style klasy są wyżej w hierarchii niż style elementu. Natomiast należy pamiętać, że dla takich samych specificity zaaplikowany będzie ostatni styl.


 #square {
    background-color: black;
  }

 #square {
    background-color: red;
  }

W tym momencie kolor zostanie już zmieniony na czerwony. Jeśli w dalszym ciągu nie rozumiesz, jak działa specificity, to skopiuj kod z poprzedniego przykładu i pobaw się nim. Najpierw usuń style inline, a następnie style #square. Zachęcam też do wypróbowania kalkulatora specificity.

Podział na pliki

Na samym początku wspomniałem, że swoje pierwsze CSS-y trzymałem w dużym napuchniętym pliku CSS. Oczywiście jest to błąd. Style należy odpowiednio wydzielić do poszczególnych plików. Sposób podziału i granulacja jest na tyle specyficzna względem konkretnego projektu, że stworzenie uniwersalnej recepty podziału mogłoby być karkołomne, a wręcz awykonalne.
Nie powinniśmy się natomiast zbytnio martwić ilością plików, ponieważ żyjemy w dobie powszechności narzędzi służących budowaniu projektów, do których należy np. Webpack. Jeśli nie znasz Webpacka, to zachęcam do zapoznania się z artykułem wprowadzającym do Webpacka. Takie narzędzia powinny za nas, podczas budowania projektu połączyć te pliki w jeden oraz zminifikować powstały kod.

Metodyki CSS

Mechanizmem, który BARDZO pomaga uporządkować selektory, są metodyki. Definiują one pewne schematy i wytyczne stylowania czy nazewnictwa klas. Samych metodyk jest całkiem sporo, a przykładowe z nich to:

  • Object Oriented CSS (OOCSS)
  • Atomic CSS (ACSS)
  • Atomic Design
  • SUIT CSS
  • Scalable and Modular Architecture for CSS (SMACSS)
  • Block Element Modifier (BEM)

Oczywiście metodyk w sieci można znaleźć sporo więcej, ale z tymi raczej spotkasz się najczęściej. Sam używam metodyki BEM. Jest ona dla mnie najwygodniejsza i w zupełności spełnia moje oczekiwania.

Nie jest to wpis będący poradnikiem BEM-a, dlatego też nie wyczerpię tematu w całości. Pokażę natomiast przykład jego zastosowania, aby zobrazować jakie problemy rozwiązuje zastosowanie metodyk.

Przykład zastosowania metodyki BEM

Załóżmy, że mamy do ostylowania formularz logowania. Formularz musi mieć pole na email oraz na hasło. Całość formularza musimy zawrzeć w jakimś kontenerze — nazwijmy go login-form. Będzie to nasz blok (B). Następnie nałóżmy klasę na pola do wpisywania danych. Stwórzmy klasę login-form__field i nałóżmy ją na każdy element <input> w formularzu. Szczególną uwagę należy zwrócić na podwójne podkreślenie, które służy do oznaczania elementu (E) w BEM. Oczywiście taki formularz musi mieć również walidację. W przypadku błędnego adresu email czy hasła pole powinno otrzymać np. czerwoną ramkę. Odpowiedzialną za to klasę nazwijmy login-form__field--invalid. Oddzielone podwójnym myślnikiem słowo invalid to modyfikator (M).

Jak widać, BEM wymusza na nas pewne wzorce nazewnictwa. Wzorce te nie tylko pomagają nam w utrzymaniu, modyfikacji i łatwej rozbudowie kodu CSS, ale też nakładają pewną abstrakcję na DOM, dzięki której nasza strona nie jest zlepkiem „div’ów” i „span’ów”, ale staje się logiczną strukturą z podziałem na bloki takie jak np. menu, toolbary, slidery itd.

Jeśli jesteś zainteresowany metodologią BEM, to w źródłach znajdziesz naprawdę sporo materiałów dotyczących BEM-a.

Podsumowanie

Uważam, że utrzymanie dobrego, łatwego w rozbudowie i utrzymaniu i czytelnego kodu CSS jest sztuką, a jednocześnie wyzwaniem. Mam nadzieję, że ten artykuł pomoże Ci w pisaniu lepszego kodu CSS, a porządkowanie kodu CSS nie będzie już dla Ciebie wyzwaniem. Oczywiście nie wyczerpałem tematu „polerowania” CSS w 100% (nie poruszyłem np. tematu preprocesorów i ich możliwości takich jak zagnieżdżenia, funkcje czy mixiny), dlatego też zachęcam do pozostawienia komentarza, jakie jeszcze sposoby na polepszenie kodu CSS znasz. Zajrzyj również do źródeł, gdzie dowiesz się więcej o omawianych zagadnieniach.

Źródła i materiał dodatkowe

Dominik Szczepaniak

Zawodowo Senior Software Engineer w CKSource. Prywatnie bloger, fan włoskiej kuchni, miłośnik jazdy na rowerze i treningu siłowego.

Inne wpisy, które mogą Cię zainteresować

Zapisz się na mailing i odbierz e-booka

Odbierz darmowy egzemplarz e-booka 106 Pytań Rekrutacyjnych Junior JavaScript Developer i realnie zwiększ swoje szanse na rozmowie rekrutacyjnej! Będziesz też otrzymywać wartościowe treści i powiadomienia o nowych wpisach na skrzynkę e-mail.

Subscribe
Notify of
guest

2 komentarzy
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Greg
4 years ago

Polecam zerknąć na poscss + pluginy są często wybawieniem. Przez autoprefixy, konwersja zmiennych, a nawet sortowanie właściwości które jak się dowiedziałem mają również wpływ na wydajność 🙂

Adam Antoszczak
Adam Antoszczak
4 years ago

Uch, nie rozumiem fascynacji BEMem. Jest irytujący jak dla mnie, bo powoduje powstawanie strasznie długich potworków w nazwach klas, bardziej podoba mi się metoda rscss.io 🙂