Modułowy CSS

Modularny CSS. Brzmi jak marzenie, a jednak część pracy została już wykonana i wydaje się, że jesteśmy na dobrej drodze do tego, aby to osiągnąć. Dzisiejszy artykuł opowiada historię CSS z perspektywy dążenia do tworzenia wydzielonych modułów.

Modułowy css PAGES.POST.COVER_THUMBNAIL.BY_WHOM DegImages

Z tego artykułu dowiesz się:

  • Co to jest enkapsulacja?

  • Jak metodyki CSS chciały naprawić problemy CSS?

  • Co to jest JSSS i jaki miała wpływ na rozwój CSS-in-JS?

  • Co to jest Interoperable CSS?

  • Jak działają moduły CSS?

Praca ze stylami zazwyczaj wygląda tak samo. Na początku jest dużo pomysłów, motywacji i deklaracji jak to tym razem będzie wspaniale. Wszak poprzednie projekty dały nam bardzo dużo doświadczenia, a stylowanie wyszło tak sobie, bo czas na projekt został ograniczony, bo zmieniły się wymagania, bo klient zmienił koncepcję, bo okazało się, że projekt jest już za drogi i czas na podniesienie jakości musimy ograniczyć. Odpalamy więc nowy projekt, tworzymy wymagane pliki i ten rollercoaster rozpoczyna kolejną przejażdżkę - niestety tym samym torem. Doprecyzowując, projekt prawdopodobnie wyszedł dobrze, ale nasze zadowolenie z kodu już nie jest już na tak wysokim poziomie. I pewnie nie będzie…

Problem z CSSem jest taki, że jest zbyt elastyczny. Pozwala nam dość luźno podejść do organizacji swojego kodu, nie narzucając nam żadnych ograniczeń architektonicznych. Wystarczy, że znamy kilka podstawowych zasad i możemy działać (czasami nawet bez nich się da). Oczywiście świat programistów szuka rozwiązań, które mogłyby zmienić CSS w coś, co będzie bardziej przewidywalne i nie tak łatwe do zepsucia. Nawet znaleziono odpowiedź: moduły.

O koncepcji modułów już pisałem. Jest na moim blogu artykuł o modułach w JS. Moduł według najprostszej definicji to samodzielna jednostka aplikacji, która ma konkretne zadanie do wykonania, nie mają na nią bezpośredniego i niekontrolowanego wpływu inne moduły, sama też nie ingeruje w działanie innych modułów. Oczywiście może być zależna, ale ta zależność najczęściej wynika z faktu, że moduł czeka na dane z innych modułów. Jedną z podstawowych cech modułów jest ich enkapsulacja.

Enkapsulacja (inaczej hermetyzacja) to termin, który najczęściej kojarzony jest z programowaniem obiektowym. W dużym skrócie chodzi w nim o to, że fragment kodu, który jest enkapsulowany jest „zabezpieczony” przed wpływem zewnętrznym na jego działanie. Innymi słowy zewnętrzne moduły nie mogą przypadkowo lub celowo zmieniać działania takiego modułu. Kiedyś na enkapsulację stosowano polski termin kapsułkowanie. Pomimo że jest to perfidna kalka językowa z angielskiego to bardzo dosadnie pomaga zrozumieć jak to działa - umieszczamy nasz kod w „kapsułce”, która zabezpiecza go przed wpływem zewnętrznym.

Skoro słowem klucz do „naprawienia” CSS jest słowo moduł - to dlaczego nie jest to takie proste? Wszystko rozbija się o fakt, że style działają globalnie dla całej aplikacji webowej. Nie mają zaimplementowanych mechanizmów, które domyślnie enkapsulowałyby nasz kod lub jego fragmenty. Ale czy na pewno? Parafrazując klasyka - potrzymaj mi piwo. Spójrzmy w przeszłość.

BEM, OOCSS i inne metodyki

To nie jest tak, że CSS pojawił się wczoraj. To też nie jest tak, że problem z CSSem, o którym wspomniałem powyżej, jest nowym wymysłem i kiedyś go nie było. BEM, jako metodyka, został zaproponowany w marcu 2009 wraz z wydaniem frameworka Lego 2.0. Yandex mierzył się z tym problemem od 2005 roku. Po 4 latach i wielu próbach doszli do wniosku, że najbezpieczniejszą formą będzie wydzielanie w ramach swoich aplikacji bloków, które są samodzielne, niezależne i reużywalne - innymi słowy - są swoistymi modułami. Każdy taki blok ma swoje własne elementy, których inne bloki nie mogą używać, bo nie mają do nich dostępu.

W styczniu 2009 roku Nicole Sullivan rozpoczęła projekt, który nazwała OOCSS (Object Oriented CSS), którego założenia były bardzo proste - pozwolić na stworzenie bardziej reużywalnego kodu, który będzie łatwy w utrzymaniu. Autorka dość mocno inspirowała się założeniami programowania obiektowego. OOCSS opiera się na dwóch założeniach: odseparowanie kontenerów od treści oraz odseparowanie struktury od wyglądu. Koncept zakłada, że klasy opisujące elementy nie będą mieszały właściwości odpowiedzialnych za strukturę: margin, padding, width, height z tymi odpowiedzialnymi za wygląd: border, color, background, font-size itp.

Co łączy obie te metodyki? Oba te podejścia (a także inne z tego okresu) osiągają podobne efekty, operując tylko i wyłącznie na nazwach klas css i konstruowaniu selektorów. Osiągają w ten sposób pewien stopień hermetyzacji. Takie podejście do CSSa ma swoje wady, przede wszystkim - wymyślanie nazw unikalnych na skalę całego projektu lub wielu projektów wykorzystujących te same pliki css może być bardzo trudne. Ponadto utrzymanie rygoru pisania w jeden określony sposób przez cały zespół nie należy do najłatwiejszych aspektów.

Powyższe próby rozwiązywały problem hermetyzacji kodu CSS. Dawały sporo satysfakcji z pisania, nawet pomimo narzekania społeczności na długie i złożone nazwy klas css.

Powrót do przeszłości

W 1996 roku firma Netscape zaproponowała alternatywę do stylowania stron www - zamiast CSS proponowano JSSS (JavaScript Style Sheets). Koncepcja JSSS zakładała, że style będą tworzone z wykorzystaniem obiektów JS. W 1997 roku zostało to wdrożone produkcyjnie. Netscape promował to podejście jako bardziej wydajne, pozwalające wykorzystywać pełne możliwości JavaScriptu jako języka programowania do obliczeń i warunkowania styli. JSSS nie posiadał dostępu do złożonych selektorów css’owych. Gdyby ta koncepcja przetrwała możliwe, że problem z modułami w CSS zostałby rozwiązany wraz z rozwinięciem koncepcji modułów w JS. Niestety tak się nie stało - żadna przeglądarka (poza Netscape Navigator) nie wprowadziła JSSS do swojego kodu.

Można by powiedzieć, że koncepcja umarła śmiercią naturalną i już nikt do niej nie wróci, ale tak się nie stało. Pomysły wykorzystania JS jako sposobu na pisanie styli wracały jak bumerang. Tak też narodziła się koncepcja CSS-in-JS. CSS-in-JS to zbiór założeń, które mają na celu pomóc pisać kod styli, tak aby unikać złożonych selektorów czy rozwiązać problemy: braku modułów, niejawnych zależności, wszechmocnych selektorów czy tak zwanych zombie-classes (martwego kodu, nieużywanego nigdzie, który trudno zlokalizować i usunąć). Przez dłuższy czas CSS-in-JS uchodziło za podejście bliskie idealnemu, na jego bazie powstało wiele nowoczesnych bibliotek, takich jak emotion, styled-components czy rozwiązania JSS.

CSS-in-JS bazuje przede wszystkim na obiektach JavaScriptowych. Enkapsulacja osiągana jest za pomocą hashowania styli. Do każdego utworzonego bloku kodu generowana jest unikalna klasa css, która powiązana jest ze stylami przypisanymi do danego komponentu. W kodzie HTML powstaje nowy element <style> zawierający informacje o tym fragmencie kodu. Poniżej napisałem jak mogłaby wyglądać bardzo prosta implementacja takiego podejścia.

W porównaniu do podejścia, o którym wspomniałem wcześniej, nazewnictwo jest zautomatyzowane, osiągamy pewien poziom hermetyzacji, ale całość kodu jest generowana przez silnik JavaScript - co wpływa na wydajność.

Problemy, o których wspomniałem powyżej w kontekście czystego CSSa, dziś zostały już częściowo rozwiązane. Podejścia takie jak BEM, OOCSS, SMACS były na dobrej drodze do osiągnięcia tego już ponad dekadę temu. Połączenie Sass’a (preprocessor CSS), wspomnianych metodyk, nowoczesnego CSSa i przede wszystkim zrozumienie jak on działa - to w moim odczuciu dużo lepsze podejście niż przepisywanie styli do JavaScriptu.

CSS Modules

Część społeczności zauważyła, że CSS-in-JS to nadal nie jest idealne rozwiązanie. Pisanie styli w obiektach JS pozbawiało nas wielu domyślnych funkcjonalności, które otrzymywaliśmy wraz z CSS. Niekiedy prowadziło do stosowania złych praktyk, takich jak użycie notacji !important do nadpisywania styli inline (część podejść CSS-in-JS dopisuje style jako właśnie inline styles).

Świat JavaScriptu od lat zmierza w kierunku tworzenia aplikacji opartych o architekturę komponentową. Z perspektywy kodu JS stworzenie i powiązanie ze sobą wielu komponentów nie stanowi zbyt dużego problemu. CSS, pomimo że zmierzał w tym kierunku, nie był w stanie nadążyć za tym nurtem z powodu braku wsparcia ze strony samego języka. Rozwiązania, które się pojawiały bardzo często były powiązane z konwencjami - tak jak BEM, a nie rozwiązaniami w samej specyfikacji języka.

W 2015 roku rozpoczęto prace na ICSS (Interoperable CSS) - rozwinięciem specyfikacji CSS, której głównym zadaniem było umożliwienie ograniczenia zasięgu styli do poziomu komponentu, jednocześnie nadal pozostawiając selektory dostępne z poziomu zasięgu globalnego. ICSS w zasadzie dodał dwa pseudoselektory CSS :import oraz :export. Ich głównym zadaniem była możliwość wyeksportowania na zewnątrz styli i zaimportowania ich w takich sposób, aby udostępnione style były dostępne jako obiekt z lokalnymi aliasami jako jego właściwościami. Lokalny alias to po prostu nazwa składająca się z liter i cyfr.

Opracowanie ICSS umożliwiło powstanie CSS Modules. CSS Module (moduł CSS) to nic innego jak plik CSS, którego wszystkie klasy oraz animacje są domyślnie ograniczone do zasięgu lokalnego. Spójrz na przykład:

CSS Modules mają przewagę nad CSS-in-JS pod względem wydajności. W CSS Modules piszesz kod CSS bez dodatkowych narzutów. Masz dostęp do wszystkich zalet zwykłego CSS bez dodatkowych narzutów.

Podsumowanie

Poprawność sprawozdawcza podpowiada mi, że w powyższym artykule brakuje sporo informacji o wadach i zaletach obu podejść. Zdaję sobie sprawę, że ugryzienie tego tematu tutaj wydłuży dość mocno ten artykuł, więc pozwolę sobie wrócić do tematu w przyszłości.

Podsumowując, świat stylowania aplikacji webowych zmieniał się na przestrzeni lat. Przez ten czas próbowano różnych podejść. Część społeczności dążyła do użycia jednego języka - JavaScriptu - do rozwiązywania wszystkich problemów. Druga grupa, do której zaliczam się i ja, postuluje, aby traktować każdy z trzech języków bardziej niezależnie, doceniać ich cechy i cele, w jakich zostały stworzone. CSS jest świetnym językiem, który dobrze użyty spełnia swoje zadania z nawiązką - pomimo, że jest językiem dość trudnym i często niedocenianym.

Moduły w CSS nadal nie istnieją, ale z wykorzystaniem powyższych podejść i stworzonych nadzbiorów dla tego języka, jesteśmy w stanie osiągnąć bardzo wiele. Łącząc metodyki, preprocessory, zrozumienie dla zasad, którymi rządzi się CSS oraz moduły jesteśmy w stanie zbudować style do naszych projektów, w taki sposób że nie będziemy musieli się ich wstydzić w przyszłości.

Udostępnij ten artykuł:

Komentarze (0)

    Jeszcze nikt nic nie napisał, ale to znaczy że... możesz być pierwszy/pierwsza.

Powiązane treści

Jeżeli ten artykuł Cię zainteresował sprawdź inne materiały powiązane z nim tematycznie. Poniżej znajdziesz artykuły i odcinki podcastów mojego autorstwa oraz polecane przeze mnie książki, które rozszerzają ten temat.

Rodziny Fontów by mediaphotos
Artykuł
09 marca 2023

Rodziny fontów

Są wszędzie. Otaczamy się nimi z każdej strony - jest ich tak dużo, że często nie zwracamy uwagę na ich różnorodność. Dziś porozmawiamy o typografii, fontach i czcionkach.

Czytaj więcej
Magia Pixel Perfect by kudou
Artykuł
11 sierpnia 2022

Magia Pixel Perfect

W czasach gdy wdzwanialiśmy się do Internetu narodziło się podejście, które zdefiniowało web development na wiele lat. Dzisiaj nie jest ono, aż tak popularne, ale według mnie warto je poznać i zrozumieć. Porozmawiajmy o magii pikseli.

Czytaj więcej
colored stones by paulbr75
Artykuł
06 sierpnia 2020

O architekturze w CSS

CSS to potrafi być prawdziwy koszmar każdego programisty. I mówię to, biorąc pełną odpowiedzialność za swoje słowa. Chaotyczny, niepoukładany i nieprzemyślany kod styli potrafi zabrać wiele godzin naszej pracy. Na szczęście jest kilka pomysłów co można z tym zrobić.

Czytaj więcej

Zapisz się do newslettera

Bądź na bieżąco z nowymi materiałami, ćwiczeniami i ciekawostkami ze świata IT. Dołącz do mnie.