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.

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
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.
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.




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