Houdini: Być może najbardziej ekscytujący rozwój CSS, o jakim nigdy nie słyszałeś

Opublikowany: 2022-03-10
Krótkie podsumowanie ↬ Czy kiedykolwiek chciałeś użyć określonej funkcji CSS, ale nie chciałeś, ponieważ nie była ona w pełni obsługiwana we wszystkich przeglądarkach ? Albo, co gorsza, było obsługiwane we wszystkich przeglądarkach, ale obsługa była błędna, niespójna, a nawet całkowicie niekompatybilna? Jeśli ci się to przydarzyło — a obstawiam, że tak się stało — powinieneś dbać o Houdiniego. Houdini to nowa grupa zadaniowa W3C, której ostatecznym celem jest, aby ten problem zniknął na zawsze. Planuje to zrobić, wprowadzając nowy zestaw interfejsów API, który po raz pierwszy da programistom możliwość rozszerzenia samego CSS oraz narzędzia umożliwiające podpięcie się do procesu stylizacji i układu silnika renderującego przeglądarki.

Czy kiedykolwiek chciałeś użyć określonej funkcji CSS, ale tego nie zrobiłeś, ponieważ nie była ona w pełni obsługiwana we wszystkich przeglądarkach ? Albo, co gorsza, było obsługiwane we wszystkich przeglądarkach, ale obsługa była błędna, niespójna, a nawet całkowicie niekompatybilna? Jeśli ci się to przydarzyło — a obstawiam, że tak się stało — powinieneś dbać o Houdiniego.

Houdini to nowa grupa zadaniowa W3C, której ostatecznym celem jest, aby ten problem zniknął na zawsze. Planuje to zrobić, wprowadzając nowy zestaw interfejsów API, który po raz pierwszy da programistom możliwość rozszerzenia samego CSS oraz narzędzia umożliwiające podpięcie się do procesu stylizacji i układu silnika renderującego przeglądarki .

Dalsze czytanie na SmashingMag:

  • Dlaczego powinieneś przestać instalować swoje środowisko WebDev lokalnie
  • Przyszłość CSS: eksperymentalne właściwości CSS
  • 53 techniki CSS, bez których nie można żyć

Ale co to konkretnie oznacza? Czy to w ogóle dobry pomysł? A w jaki sposób pomoże nam, programistom, budować strony internetowe teraz iw przyszłości?

Więcej po skoku! Kontynuuj czytanie poniżej ↓

W tym artykule postaram się odpowiedzieć na te pytania. Ale zanim to zrobię, ważne jest, aby wyjaśnić, jakie problemy są dzisiaj i dlaczego istnieje taka potrzeba zmian. Następnie opowiem bardziej szczegółowo o tym, jak Houdini rozwiąże te problemy i wymienię niektóre z bardziej ekscytujących funkcji, które są obecnie opracowywane. Na koniec przedstawię kilka konkretnych rzeczy, które my, twórcy stron internetowych, możemy dziś zrobić, aby pomóc w urzeczywistnieniu Houdini.

Jakie problemy próbuje rozwiązać Houdini?

Za każdym razem, gdy piszę artykuł lub tworzę demo pokazujące nową funkcję CSS, nieuchronnie ktoś w komentarzach lub na Twitterze powie coś w stylu: „To jest niesamowite! Szkoda, że ​​nie będziemy mogli go używać przez kolejne 10 lat.”

Takie komentarze są irytujące i niekonstruktywne, ale rozumiem ten sentyment. Historycznie rzecz ujmując, mijało lata, zanim propozycje nowych funkcji zyskały powszechne przyjęcie. Powodem jest to, że w całej historii sieci jedynym sposobem na dodanie nowej funkcji do CSS było przejście przez proces standardów.

Proces norm
Kroki w procesie normalizacji. (Wyświetl dużą wersję)

Chociaż nie mam absolutnie nic przeciwko procesowi standardów, nie można zaprzeczyć, że może to zająć dużo czasu!

Na przykład flexbox został po raz pierwszy zaproponowany w 2009 roku, a programiści wciąż narzekają, że nie mogą go dziś używać z powodu braku obsługi przeglądarek. To prawda, że ​​ten problem powoli znika, ponieważ prawie wszystkie nowoczesne przeglądarki aktualizują się teraz automatycznie; ale nawet w przypadku nowoczesnych przeglądarek zawsze będzie opóźnienie między propozycją a ogólną dostępnością funkcji.

Co ciekawe, nie dotyczy to wszystkich obszarów sieci. Zastanów się, jak ostatnio wszystko działało w JavaScript:

Proces Polyfill
Etapy procesu wypełniania. (Wyświetl dużą wersję)

W tym scenariuszu czas między pomysłem a wykorzystaniem go w produkcji może być czasem kwestią kilku dni. To znaczy, używam już funkcji async / await w produkcji, a ta funkcja nie została zaimplementowana nawet w jednej przeglądarce!

Widać też ogromną różnicę w ogólnych nastrojach tych dwóch społeczności. W społeczności JavaScript czytasz artykuły, w których ludzie narzekają, że sprawy toczą się zbyt szybko. Z drugiej strony w CSS słyszysz, jak ludzie narzekają na daremność uczenia się czegokolwiek nowego ze względu na to, ile czasu minie, zanim będą mogli z tego korzystać.

Dlaczego więc po prostu nie napiszemy więcej wypełniaczy CSS?

Na pierwszy rzut oka pisanie większej liczby wypełniaczy CSS może wydawać się odpowiedzią. Z dobrymi wypełnieniami CSS może działać tak szybko jak JavaScript, prawda?

Niestety nie jest to takie proste. Wypełnianie CSS jest niezwykle trudne i w większości przypadków niemożliwe do wykonania w sposób, który nie niszczy całkowicie wydajności.

JavaScript jest językiem dynamicznym, co oznacza, że ​​możesz używać JavaScript do wypełniania kodu JavaScript. A ponieważ jest tak dynamiczny, jest niezwykle rozciągliwy. Z drugiej strony CSS rzadko może być używany do wypełniania CSS. W niektórych przypadkach możesz transpilować CSS do CSS w kroku kompilacji (robi to PostCSS); ale jeśli chcesz wypełniać wszystko, co zależy od struktury DOM lub układu lub pozycji elementu, musisz uruchomić logikę wypełniania po stronie klienta.

Niestety przeglądarka nie ułatwia tego.

Poniższy wykres przedstawia podstawowe informacje o tym, jak Twoja przeglądarka przechodzi od otrzymywania dokumentu HTML do wyświetlania pikseli na ekranie. Kroki zaznaczone na niebiesko pokazują, gdzie JavaScript może kontrolować wyniki:

Proces renderowania
Dostęp JavaScript do potoku renderowania przeglądarki. (Wyświetl dużą wersję)

Obraz jest dość ponury. Jako programista nie masz kontroli nad tym, jak przeglądarka analizuje kod HTML i CSS oraz przekształca go w model obiektowy DOM i CSS (CSSOM). Nie masz kontroli nad kaskadą. Nie masz kontroli nad tym, jak przeglądarka wybiera układ elementów w DOM lub jak maluje te elementy wizualnie na ekranie. I nie masz kontroli nad tym, co robi kompozytor.

Jedyną częścią procesu, do której masz pełny dostęp, jest DOM. CSSOM jest nieco otwarty; jednak, cytując witrynę Houdini, jest „niedookreślona, ​​niespójna w różnych przeglądarkach i brakuje jej krytycznych funkcji”.

Na przykład CSSOM w dzisiejszych przeglądarkach nie pokaże reguł dla arkuszy stylów z różnych źródeł i po prostu odrzuci wszystkie reguły lub deklaracje CSS, których nie rozumie, co oznacza, że ​​jeśli chcesz ponownie wypełnić funkcję w przeglądarce który tego nie obsługuje, nie możesz używać CSSOM. Zamiast tego musisz przejść przez DOM, znaleźć tagi <style> i/lub <link rel=“stylesheet”> , samodzielnie pobrać CSS, przeanalizować go, przepisać i dodać z powrotem do DOM.

Oczywiście aktualizacja DOM zwykle oznacza, że ​​przeglądarka musi przejść przez całą kaskadę, układ, malowanie i składanie od nowa.

Proces renderowania Polyfilled
Ponowne wypełnianie potoku renderowania przeglądarki za pomocą JavaScript. (Wyświetl dużą wersję)

Chociaż konieczność całkowitego zrenderowania strony może nie wydawać się dużym hitem wydajności (szczególnie w przypadku niektórych witryn), zastanów się, jak często musi się to zdarzać. Jeśli logika twojego wypełniacza musi działać w odpowiedzi na takie rzeczy, jak przewijanie, zmiana rozmiaru okna, ruchy myszy, zdarzenia klawiatury — naprawdę za każdym razem, gdy wszystko się zmienia — wtedy wszystko będzie zauważalnie, czasem nawet paraliżujące, powolne.

Sytuacja staje się jeszcze gorsza, gdy zdasz sobie sprawę, że większość dostępnych obecnie wypełniaczy CSS zawiera własny parser CSS i własną logikę kaskadową. A ponieważ parsowanie i kaskada są w rzeczywistości bardzo skomplikowanymi rzeczami, te wypełnienia są zwykle albo zbyt duże, albo zbyt błędne.

Podsumowując wszystko, co właśnie powiedziałem bardziej zwięźle: jeśli chcesz, aby przeglądarka robiła coś innego niż myśli, że powinna robić (biorąc pod uwagę CSS, który jej podałeś), musisz znaleźć sposób na sfałszowanie tego, aktualizując i modyfikując sam DOM. Nie masz dostępu do innych kroków potoku renderowania.

Ale dlaczego miałbym kiedykolwiek chcieć modyfikować wewnętrzny silnik renderujący przeglądarki?

To jest dla mnie absolutnie najważniejsze pytanie, na które należy odpowiedzieć w całym tym artykule. Tak więc, jeśli do tej pory przeglądałeś rzeczy, przeczytaj tę część powoli i uważnie!

Po obejrzeniu ostatniej sekcji jestem pewien, że niektórzy z was pomyśleli: „Nie potrzebuję tego! Po prostu tworzę normalne strony internetowe. Nie próbuję włamywać się do wnętrza przeglądarki ani budować czegoś super wymyślnego, eksperymentalnego lub najnowocześniejszego”.

Jeśli tak myślisz, gorąco zachęcam do cofnięcia się na chwilę i dokładnego przeanalizowania technologii, których używałeś do tworzenia witryn internetowych na przestrzeni lat. Chęć dostępu i zaczepianie się w procesie stylizacji przeglądarki to nie tylko tworzenie wymyślnych wersji demonstracyjnych — chodzi o umożliwienie programistom i autorom frameworków dwóch podstawowych rzeczy:

  • znormalizować różnice między przeglądarkami,
  • wymyślać lub wypełniać nowe funkcje, aby ludzie mogli z nich korzystać już dziś.

Jeśli kiedykolwiek korzystałeś z biblioteki JavaScript, takiej jak jQuery, to już skorzystałeś z tej możliwości! W rzeczywistości jest to jeden z głównych punktów sprzedaży prawie wszystkich dzisiejszych bibliotek i frameworków front-end. Pięć najpopularniejszych repozytoriów JavaScript i DOM na GitHub — AngularJS, D3, jQuery, React i Ember — wykonuje dużo pracy, aby znormalizować różnice między przeglądarkami, abyś nie musiał o tym myśleć. Każdy udostępnia pojedynczy interfejs API i po prostu działa.

Teraz pomyśl o CSS i wszystkich jego problemach z różnymi przeglądarkami. Nawet popularne frameworki CSS, takie jak Bootstrap i Foundation, które twierdzą, że są zgodne z różnymi przeglądarkami, w rzeczywistości nie normalizują błędów w różnych przeglądarkach — po prostu ich unikają. Błędy występujące w różnych przeglądarkach w CSS to już nie tylko przeszłość. Nawet dzisiaj, dzięki nowym modułom układu, takim jak flexbox, napotykamy wiele niezgodności między przeglądarkami.

Najważniejsze jest to, wyobraź sobie, o ile przyjemniejsze byłoby twoje życie programistyczne, gdybyś mógł użyć dowolnej właściwości CSS i mieć pewność, że będzie działać dokładnie tak samo w każdej przeglądarce. I pomyśl o wszystkich nowych funkcjach, o których czytasz w postach na blogach lub słyszysz o nich na konferencjach i spotkaniach — takich jak siatki CSS, punkty przyciągania CSS i pozycjonowanie przyklejone. Wyobraź sobie, że możesz używać ich wszystkich już dziś i to w sposób równie wydajny , jak natywne funkcje CSS. Wszystko, co musisz zrobić, to pobrać kod z GitHub.

To jest marzenie Houdiniego. To jest przyszłość, którą zespół zadaniowy stara się umożliwić.

Tak więc, nawet jeśli nigdy nie planujesz pisać wypełniacza CSS ani rozwijać funkcji eksperymentalnej, prawdopodobnie chciałbyś, aby inni ludzie mogli to zrobić — ponieważ gdy te wypełniacze istnieją, wszyscy z nich korzystają.

Jakie funkcje Houdini są obecnie w fazie rozwoju?

Wspomniałem powyżej, że programiści mają bardzo mało punktów dostępu do potoku renderowania przeglądarki. Tak naprawdę jedyne miejsca to DOM i do pewnego stopnia CSSOM.

Aby rozwiązać ten problem, grupa zadaniowa Houdini wprowadziła kilka nowych specyfikacji, które po raz pierwszy zapewnią programistom dostęp do innych części potoku renderowania. Poniższy wykres przedstawia potok i nowe specyfikacje, które można wykorzystać do modyfikacji poszczególnych kroków. (Pamiętaj, że specyfikacje zaznaczone na szaro są planowane, ale jeszcze nie zostały napisane.)

Zakres specyfikacji
Gdzie nowe specyfikacje Houdini pasują do potoku renderowania przeglądarki. (Wyświetl dużą wersję)

W następnych kilku sekcjach znajduje się krótki przegląd każdej nowej specyfikacji i rodzajów oferowanych przez nią możliwości. Powinienem również zauważyć, że inne specyfikacje nie są wymienione w tym artykule; pełna lista znajduje się w repozytorium wersji roboczych Houdiniego na GitHub.

API parsera CSS

CSS Parser API nie jest obecnie napisany; więc wiele z tego, co powiem, można łatwo zmienić, ale podstawową ideą jest to, że umożliwia programistom rozszerzenie parsera CSS i poinformowanie go o nowych konstrukcjach — na przykład o nowych regułach dotyczących mediów, nowych pseudoklasach, zagnieżdżaniu, @extends , @apply itp.

Gdy parser wie o tych nowych konstrukcjach, może umieścić je we właściwym miejscu w CSSOM, zamiast po prostu je odrzucać.

API właściwości i wartości CSS

CSS ma już niestandardowe właściwości i, jak już wcześniej wyraziłem, jestem bardzo podekscytowany możliwościami, które odblokowują. Interfejs API właściwości i wartości CSS przenosi niestandardowe właściwości o krok dalej i czyni je jeszcze bardziej użytecznymi, dodając typy.

Jest wiele wspaniałych rzeczy związanych z dodawaniem typów do właściwości niestandardowych, ale być może największą zaletą jest to, że typy umożliwiają programistom przenoszenie i animowanie właściwości niestandardowych, czego nie możemy dziś zrobić.

Rozważ ten przykład:

 body { --primary-theme-color: tomato; transition: --primary-theme-color 1s ease-in-out; } body.night-theme { --primary-theme-color: darkred; }

W powyższym kodzie, jeśli klasa night-theme zostanie dodana do elementu <body> , każdy element na stronie, który odwołuje się do wartości właściwości –primary-theme-color , będzie powoli przechodził z tomato do darkred . Gdybyś chciał to zrobić dzisiaj, musiałbyś ręcznie napisać przejście dla każdego z tych elementów, ponieważ nie możesz przenieść samej właściwości.

Inną obiecującą funkcją tego interfejsu API jest możliwość zarejestrowania „zastosowania haka”, co daje programistom możliwość modyfikowania końcowej wartości niestandardowej właściwości elementów po zakończeniu kroku kaskadowego, co może być bardzo przydatną funkcją w przypadku wypełniaczy.

CSS wpisany OM

CSS Typeed OM można traktować jako wersję 2 obecnego CSSOM. Jego celem jest rozwiązanie wielu problemów z obecnym modelem oraz uwzględnienie funkcji dodanych przez nowy CSS Parsing API oraz CSS Properties and Values ​​API.

Innym ważnym celem Typed OM jest poprawa wydajności. Przekształcenie bieżących wartości ciągów CSSOM w sensownie wpisane reprezentacje JavaScript przyniosłoby znaczny wzrost wydajności.

API układu CSS

Interfejs API układu CSS umożliwia programistom pisanie własnych modułów układu. A przez „moduł układu” rozumiem wszystko, co można przekazać do właściwości display CSS. Da to programistom po raz pierwszy sposób na zaprojektowanie układu, który jest równie wydajny, jak natywne moduły układu, takie jak display: flex i display: table .

Jako przykładowy przypadek użycia, biblioteka układów Masonry pokazuje, w jakim stopniu programiści są gotowi iść dzisiaj, aby osiągnąć złożone układy, których nie można osiągnąć za pomocą samego CSS. Chociaż te układy są imponujące, niestety cierpią na problemy z wydajnością, zwłaszcza na słabszych urządzeniach.

Interfejs API układu CSS działa, udostępniając programistom metodę registerLayout , która akceptuje nazwę układu (która jest później używana w CSS) i klasę JavaScript, która zawiera całą logikę układu. Oto podstawowy przykład, jak można zdefiniować masonry za pomocą registerLayout :

 registerLayout('masonry', class { static get inputProperties() { return ['width', 'height'] } static get childrenInputProperties() { return ['x', 'y', 'position'] } layout(children, constraintSpace, styleMap, breakToken) { // Layout logic goes here. } }

Jeśli nic w powyższym przykładzie nie ma dla Ciebie sensu, nie martw się. Najważniejszą rzeczą, na której należy się zwrócić, jest kod w następnym przykładzie. Po pobraniu pliku masonry.js i dodaniu go do swojej witryny możesz napisać CSS w ten sposób i wszystko będzie po prostu działać:

 body { display: layout('masonry'); }

CSS Paint API

Interfejs API CSS Paint jest bardzo podobny do powyższego interfejsu API układu. Udostępnia metodę registerPaint , która działa podobnie jak metoda registerLayout . Deweloperzy mogą następnie użyć funkcji paint() w CSS wszędzie tam, gdzie oczekiwany jest obraz CSS i przekazać nazwę, która została zarejestrowana.

Oto prosty przykład, który maluje kolorowe kółko:

 registerPaint('circle', class { static get inputProperties() { return ['--circle-color']; } paint(ctx, geom, properties) { // Change the fill color. const color = properties.get('--circle-color'); ctx.fillStyle = color; // Determine the center point and radius. const x = geom.width / 2; const y = geom.height / 2; const radius = Math.min(x, y); // Draw the circle \o/ ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI, false); ctx.fill(); } });

I można go używać w CSS w ten sposób:

 .bubble { --circle-color: blue; background-image: paint('circle'); }

Teraz element .bubble będzie wyświetlany z niebieskim kółkiem jako tłem. Okrąg będzie wyśrodkowany i będzie miał taki sam rozmiar jak sam element, cokolwiek to będzie.

Worklety

Wiele specyfikacji wymienionych powyżej zawiera przykłady kodu (na przykład registerLayout i registerPaint ). Jeśli zastanawiasz się, gdzie umieściłbyś ten kod, odpowiedź znajduje się w skryptach worklet.

Worklety są podobne do procesów sieciowych i umożliwiają importowanie plików skryptów i uruchamianie kodu JavaScript, który (1) może być wywoływany w różnych punktach potoku renderowania oraz (2) jest niezależny od głównego wątku.

Skrypty robocze mocno ograniczają typy operacji, które możesz wykonywać, co ma kluczowe znaczenie dla zapewnienia wysokiej wydajności.

Złożone przewijanie i animacja

Chociaż nie ma jeszcze oficjalnej specyfikacji dla złożonego przewijania i animacji, w rzeczywistości jest to jedna z bardziej znanych i wyczekiwanych funkcji Houdini. Ewentualne API pozwolą programistom na uruchamianie logiki w robocie kompozytora, poza głównym wątkiem, z obsługą modyfikacji ograniczonego podzbioru właściwości elementu DOM. Ten podzbiór będzie zawierał tylko właściwości, które można odczytać lub ustawić bez zmuszania silnika renderującego do ponownego obliczenia układu lub stylu (na przykład przekształcenie, krycie, przesunięcie przewijania).

Umożliwi to programistom tworzenie wysoce wydajnych animacji opartych na przewijaniu i wprowadzaniu danych, takich jak lepkie nagłówki przewijania i efekty paralaksy. Możesz przeczytać więcej o przypadkach użycia, które te interfejsy API próbują rozwiązać w serwisie GitHub.

Chociaż nie ma jeszcze oficjalnej specyfikacji, eksperymentalny rozwój w Chrome już się rozpoczął. W rzeczywistości zespół Chrome obecnie wdraża punkty przyciągania CSS i pozycjonowanie przyklejone za pomocą prymitywów, które te interfejsy API ostatecznie ujawnią. To niesamowite, ponieważ oznacza to, że interfejsy API Houdini są wystarczająco wydajne, aby na ich podstawie budowane były nowe funkcje Chrome. Jeśli nadal obawiałeś się, że Houdini nie będzie tak szybki jak tubylec, sam ten fakt powinien cię przekonać, że jest inaczej.

Aby zobaczyć prawdziwy przykład, Surma nagrała wideo demo działające na wewnętrznej kompilacji Chrome. Demo naśladuje zachowanie nagłówka przewijania widoczne w natywnych aplikacjach mobilnych Twittera. Aby zobaczyć, jak to działa, sprawdź kod źródłowy.

Co możesz teraz zrobić?

Jak wspomniano, myślę, że każdy, kto buduje strony internetowe, powinien dbać o Houdini; w przyszłości znacznie ułatwi nam życie. Nawet jeśli nigdy nie używasz bezpośrednio specyfikacji Houdini, prawie na pewno użyjesz czegoś zbudowanego na jednej z nich.

I chociaż ta przyszłość może nie być natychmiastowa, prawdopodobnie jest bliżej niż wielu z nas myśli. Przedstawiciele wszystkich głównych dostawców przeglądarek byli na ostatnim spotkaniu twarzą w twarz Houdini w Sydney na początku tego roku i było bardzo niewiele sporów co do tego, co zbudować lub jak postępować.

Z tego, co mogłem powiedzieć, nie chodzi o to, czy Houdini będzie czymś, ale kiedy i tu wszyscy się pojawicie.

Dostawcy przeglądarek, podobnie jak wszyscy, którzy tworzą oprogramowanie, muszą nadać priorytet nowym funkcjom. A ten priorytet jest często funkcją tego, jak bardzo użytkownicy chcą tych funkcji.

Jeśli więc zależy Ci na rozszerzalności stylizacji i układu w sieci oraz jeśli chcesz żyć w świecie, w którym możesz korzystać z nowych funkcji CSS bez konieczności czekania, aż przejdą przez proces standardów, porozmawiaj z członkami zespoły ds. relacji z programistami dla przeglądarek, których używasz, i powiedz im, że tego chcesz.

Innym sposobem, w jaki możesz pomóc, jest dostarczanie rzeczywistych przypadków użycia — rzeczy, które chcesz zrobić ze stylami i układem, które są dziś trudne lub niemożliwe do wykonania. Kilka wersji roboczych na GitHub zawiera dokumentację przypadków użycia i możesz przesłać żądanie ściągnięcia, aby wnieść swoje pomysły. Jeśli dokument nie istnieje, możesz go uruchomić.

Członkowie grupy zadaniowej Houdini (i ogólnie W3C) naprawdę chcą przemyślanego wkładu od twórców stron internetowych. Większość osób biorących udział w procesie pisania specyfikacji to inżynierowie pracujący w przeglądarkach. Często sami nie są profesjonalnymi programistami internetowymi, co oznacza, że ​​nie zawsze wiedzą, gdzie są problemy.

Zależą od nas, że im powiemy.

Zasoby i linki

  • CSS-TAG Houdini Editor Drafts, W3C Najnowsza publiczna wersja wszystkich projektów Houdini
  • CSS-TAG Houdini Task Force Specifications, GitHub Oficjalne repozytorium Github, w którym odbywa się aktualizacja specyfikacji i rozwój
  • Próbki Houdini, przykłady kodu GitHub prezentujące i eksperymentujące z możliwymi interfejsami API
  • Lista mailingowa Houdini, W3C Miejsce do zadawania ogólnych pytań

Specjalne podziękowania dla członków Houdini, Iana Kilpatricka i Shane'a Stephensa, za przejrzenie tego artykułu.