css houdini ach te internety

Zaprzyjaźnijmy się z CSS Houdini

Znacie grupę The Illusionists? To zespół niewiarygodnie dobrych iluzjonistów, magików, akrobatów. Byłam raz na ich występie. Jednym z pokazów była słynna sztuczka Houdiniego – ucieczka ze skrzyni wypełnionej wodą. Wykonywał ją Andrew Basso. Nie wiem, ile było w niej iluzji, ile brawury, ile doświadczenia, ile po prostu głupiego szczęścia. Jednego jestem pewna – było to przedstawienie wręcz hipnotyczne.

Już zaraz, już za chwilę, ty również będziesz mógł robić takie spektakle. W przeglądarce, dosłownie…

Uwaga – celem tego artykułu nie jest szczegółowa specyfikacja Houdiniego. Broń Boże. Ten artykuł jest dla osób zielonych w temacie, które chciałyby szybko zdobyć wiedzę minimalną do wzięcia udziału w branżowym small talk. Ewentualnie kogoś poderwać w barze po północy.

Problematyczny CSS

CSS często nie odpowiada na wszystkie problemy współczesnego programisty. Niby tyle możliwości, a jednak… dla nas to ciągle mało. Przykłady?

  • Brak wsparcia dla niektórych funkcjonalności lub różnice w ich obsłudze wśród różnych przeglądarek.
  • Brak konkretnych funkcjonalności, np. obsługi własnych atrybutów CSS, specyficznych layoutów (masonry), obsługi zdarzenia scrolla, itd.

Wiele z tych problemów obchodzimy, niczym iluzjoniści, samozwańczy Houdini – za pomocą zwykłego Javascriptu. A konkretnie polyfillów. Przyzwyczailiśmy się do nich, jak do wejść na produkcję w piątek o godz. 16:00. Ot, są częścią naszej rzeczywistości i tyle. Ale czy aby na pewno powinniśmy tak bezkrytycznie do nich podchodzić?

Polyfillu, czas się rozstać.

Otóż przyjrzyjmy się dokładniej polyfillom do CSSa. Niestety, w odróżnieniu od polyfillów do JS, często są one obarczone problemami wydajnościowymi. Spójrz tylko na poniższy proces renderowania się strony.

proces-renderowania
Źródło

A tak wygląda proces renderowania z użyciem polyfilla:

Źródło

Oto standardowa ścieżka renderowania strony. Parser tworzy 2 obiekty DOM i CSSOM, które są łączone w fazie cascade. Na tym etapie przeglądarka wie, jakie style nadać konkretnym elementom. Następnie w fazie layout określana jest geometria elementów – wyliczane są ich wielkości oraz położenie w przestrzeni 2D. Faza paint to malowanie albo inaczej rasteryzacja, czyli przekształcenia każdego węzła w drzewie renderowania na rzeczywiste piksele na ekranie. Ostatecznie wszystkie warstwy są składane do końcowego widoku w fazie composite. I dopiero w tym momencie w grę wchodzi nasz polyfill.

W zależności od swojego przeznaczenia modyfikuje on DOM i, w miarę możliwości, CSSOM. Dla przykładu chcemy dodać obsługę customowych atrybutów (np. w przypadku CSS Grid). Nasz polyfill, podobnie jak większość używanych polyfillów we wszechświecie, posiada własny parser CSS, który po raz kolejny mieli cały kod. Wydobywa z niego wszystkie style, wyłuskuje atrybuty nieobsługiwane przez przeglądarkę, a następnie przepisuje DOM i/lub CSSOM. Oczywiście wszelkie zmiany inicjują wznowienie procesu renderowania! Przerobiliśmy już dwa parsowania, a teraz apiać od nowa po raz kolejny lecą cascade -> layout -> paint -> composite. Brzmi niewydajnie, co nie? I takie jest. Nie wspominając o tym, że ze względu na częstą konieczność posiadania własnego parsera polyfille są duże, skomplikowane i naszpikowane błędami.

Wyobraź sobie teraz najczerniejszy z czarnych scenariuszy – twój polyfill musi reagować na zdarzenia typu scroll, zmiana szerokości okna, ruch myszką. Niewiele brakuje, żeby liczba momentów wywołujących nadmiarowe rerendery okazała się wystarczająco duża, aby skutecznie popsuć przyjemność użytkowania strony.

Na tym etapie, kiedy płaczemy w poduszkę z frustracji i bezsilności, na horyzoncie pojawia się nasz wybawca – CSS Houdini.

Źródło

CSS Houdini, czym jesteś?

CSS Houdini to bohater, który rozwiązuje wszystkie powyższe problemy. I nie tylko. Pozwala na wpinanie się w poszczególne etapy renderowania, dzięki czemu cały proces renderowania zachodzi tylko raz. Daje dostęp do silnika CSS, do całej czarnej, niskopoziomowej magii przeglądarek związanej z renderowaniem.

Kiedy nasze biedne polyfille jedynie imitują CSS, co jak wiemy jest super-niewydajne, Houdini umożliwia rozszerzenie CSS za pomocą JS. Pufff, i stała się magia. Wyobraź sobie świat bez różnic w obsłudze CSSa pomiędzy przeglądarkami. Świat, w którym możesz użyć każdej, nawet najnowszej fancy, experimental funkcjonalności CSS znanej tylko z internetu i ona ot tak po prostu będzie działać.

Houdini to pojęcie parasolka, pod którym znajduje się kilka różnych API. Umożliwiają dodawanie nowych funkcjonalności do CSS (np. tak bardzo pożądana obsługa customowych atrybutów), tworzenie wydajnych, zaawansowanych animacji, dają dostęp do CSSOM, do każdego etapu renderowania, do parsera. Houdini to władza nad przeglądarką. Spójrz tylko na poniższy proces renderowania uwzględniający jego możliwości.

Źródło

Wszystkie specyfikacje znajdujące się pod kapturkiem o nazwie Houdini – znajdziesz TUTAJ.

Brzmi pięknie, ale jest jeden mały szkopuł tej idyllicznej wizji – tylko niektóre z owych tajemniczych API są zaimplementowane w niektórych przeglądarkach. Meh. Jeśli interesują Ciebie konkrety: wejdź na Is Houdini ready yet? i sprawdź tabelę, która zgrabnie prezentuje obecny stan dostępności poszczególnych składowych Houdini’ego.

Stan na 5.01.2020. Is Houdini ready yet?

I w sumie na tym mogłabym zakończyć artykuł. Nie założyłam tego bloga, aby dzielić się długimi formami pisemnymi. Jednak czuję pewien niedosyt informacyjny, więc opiszę Ci jeszcze, tak pokrótce, najważniejsze składowe projektu o nazwie Houdini. Do dzieła.

Pokaż kotku, co masz w środku.

Parser API

Standardowy parser CSS pomija nieznane konstrukcje. Parser API rozszerza jego możliwości. Umożliwia np. wprowadzenie nowych pseudoselektorów, selektorów, jednostek. Dzięki temu parser tworzy poprawny CSSOM uwzględniający nowe konstrukcje.

Properties & Values API

Znamy już zmienne CSS. Houdini rozszerza ich możliwości za pomocą CSS Properties & Values API. Pozwala zdefiniować nie tylko nazwy zmiennej, ale też określony typ (np. color, image, url, time, …), określa informację o dziedziczeniu, czy wartości początkowej. Te wszystkie nowości umożliwiają np. animacje oparte na zmiennych.

Mało tego, częścią Properties & Values API jest Typed OM.

Typed OM

Następca CSSOM.

Wartości w CSSOM to zwykłe stringi (np. "20px", "0.3"), co okazuje się gigantycznie kłopotliwym faktem, kiedy próbujesz daną wartość zaktualizować, zmienić za pomocą działania matematycznego (np. document.body.style.opacity += 0.3).

CSS TOM przedstawia wartości CSS jako obiekty JS o typie CSSStyleValue oraz określonej strukturze. Przykłady podtypów wartości CSS:

  • CSSKeywordValue słowa klucze np. inheritgrid, baseline
  • CSSPositionValue wartości pozycji w przestrzeni
  • CSSImageValueobraz
  • CSSUnitValuewartości z jednostką miary, np. 50px
  • CSSTransformValue wartości dostępne dla właściwości transform

CSS TOM to również podstawowe operacje matematyczne, konwersja jednostek, walidacja typów, automatyczne zaokrąglanie podanych wartości do akceptowanych miar, obsługa błędów.

Font Metrics API

Udostępnia szczegółowe informacje dotyczące wyrenderowanego tekstu, np. rodzaj użytego fontu, jego rozmiar, pozycja baseline, sposób łamania.

Worklety

Worklet to zwykła klasa znana ci z ES6 napisana w osobnym, dedykowanym dla workleta pliku JS. Posiada określony cel, który realizuje implementując konkretny interfejs CSS Houdini. Po rejestracji worklet może być wołany z poziomu kodu CSS.

Istotny jest fakt, iż to przeglądarka tworzy instancje danych klas. Kontroluje obiekty: tworzy je, niszczy, decyduje o ich ilości oraz momencie użycia.

Worklety są totalnie pozbawione dostępu do danych z zewnątrz (ani do obiektu window, ani document, danych aplikacji, funkcji globalnych typu alert – niczego!). Każdy worklet żyje w osobnym wątku i ma wykonywać ściśle określone zadanie.

Wszystko w jednym celu – worklet musi być lekki i szybki, aby zgrabnie imitować natywną funkcjonalność przeglądarki. Niektóre animacje mogą wywoływać go nawet kilkadziesiąt razy w ciągu sekundy – tu nie ma miejsca (czasu) na zbędny kod.

Layout API

Umożliwia tworzenie własnych layoutów, przekazywanych następnie do własności CSS display. Daje furtkę do tworzenia np. wydajnych układów typu masonry.

Przy okazji może służyć do implementacji filtrowania na stronie za pomocą mechanizmów pokazywania / ukrywania elementów.

Implementowany za pomocą pliku worklet.

Paint API

Tworzenie grafik za pomocą składni podobnej do canvas, przekazywanych następnie do takich własności CSS jak background-image, border-image, mask-image.

Sposób implementacji: worklet.

AnimationWorklet / Animation API

Wydajne animacje niezależne od czasu, np. oparte na działaniu użytkownika na stronie. Animation API umożliwi stworzenie np. wydajnego efektu parallax, który bazuje na zdarzeniu scroll, czyli przewijania strony. Innym przykładem punktu odniesienia animacji, alternatywnym do czasu, jest miara postępu podczas wgrywania pliku.

Scroll Customization API

Umożliwi stylowanie paska scrolla, a także określenie sposobu przewijania elementu w zależności od przewijania całej strony.

Czy wyeliminuje scroll jacking? Oj, miejmy nadzieję!

Przykłady

CSS HOUDINI experimental showcase by @iamvdo

Kilka przykładów znajdziesz również na CSS at Chrome Dev Summit.

Uwaga – aby zobaczyć niektóre przykłady w Google Chrome, musisz wejść na chrome://flags/, włączyć opcję „Experimental Web Platform features”, a następnie uruchomić ponownie przeglądarkę.

Houdini, czyli władza i odpowiedzialność.

CSS Houdini to projekt, którym powinien interesować się każdy front-end developer. W niedalekiej przyszłości będzie on odgrywał znaczącą rolę w branży. I w końcu pojęcie “człowiek od CSSa” będzie brzmiało dumnie.

Koniecznie daj znać w komentarzu, co myślisz o CSS Houdini?

Pisz również, jeśli chcesz, abym dokładniej opisała konkretne API z podwórka CSS Houdini w osobnym artykule.


Źródła, rozwinięcia tematu:


Źródło głównego zdjęcia z pokazu The Illusionists.

Artykuły, które mogą Ci się spodobać...

Wpisz hasło, którego szukasz i naciśnij ENTER, aby je wyszukać. Naciśnij ESC, aby anulować.

Dawaj na górę