Jest powód, dla którego parallax w JavaScripcie zawsze wygląda odrobinę nie tak – lekko odklejony, jakby warstwy pływały pół klatki za stroną. To nie niechlujny kod. To fakt, że zdarzenia scrolla docierają do twojego JavaScriptu już po tym, jak przeglądarka narysowała przewinięcie. Przeglądarka rozwiązała to już raz, zamieniając przyklejone nagłówki w position: sticky. Scroll-driven animations to ten sam ruch, zastosowany od razu do wszystkich efektów powiązanych ze scrollem.
Przez dziesięć lat animowanie miniatury w duży obraz oznaczało jedną technikę: zmierz element przed, zmierz po, udawaj różnicę transformem i puść. FLIP. Robi to każda biblioteka animacji i każda płaci za to JavaScriptem na głównym wątku w najgorszym możliwym momencie. View Transitions API przenosi całą tę sztuczkę do przeglądarki – a od Reacta 19.2 i Next.js 16 całym kontraktem jest jeden prop o nazwie name.
Lista tysiąca komentarzy renderuje się wolno, więc sięgasz po react-window – i w zamian za płynny scroll tracisz Ctrl+F, drukowanie strony i częściowo nawigację czytnika ekranu, bo elementy poza oknem przestają fizycznie istnieć w DOM. content-visibility rozwiązuje ten sam problem inaczej: elementy zostają w DOM, przeglądarka po prostu pomija dla nich kosztowną pracę layoutu i malowania, dopóki nie znajdą się blisko widocznego obszaru – i, co zaskakujące, potrafi je tymczasowo odsłonić, gdy szukasz w nich tekstu.
W artykule o dostępności modal z display:none, który dalej istniał w drzewie dostępności, był przykładem błędu wynikającego z budowania modala od zera na divach. Prawdziwe pytanie brzmi: dlaczego w ogóle trzeba było go budować od zera? Sprawdzam, co daje za darmo natywny <dialog> i atrybut popover – top layer, pułapkę fokusu, light dismiss – i gdzie te dwa mechanizmy się różnią na tyle, że pomylenie ich to prosta droga do niedostępnego interfejsu.
Klasa narzędziowa .mt-4 przegrywa z regułą .card .card__header .card__title, mimo że logicznie powinna wygrać, bo dodano ją później. To nie przypadek – to specyficzność robiąca dokładnie to, do czego została zaprojektowana. @layer wprowadza całkiem nową oś rozstrzygania konfliktów, która działa przed specyficznością, nie razem z nią – i ma jedną pułapkę tak nieintuicyjną, że łamie ją nawet część dokumentacji w sieci.
Pole formularza ma się podświetlić na czerwono, gdy input w środku jest niepoprawny. Prosta rzecz – tylko że CSS przez 25 lat nie potrafił zapytać elementu o to, co się dzieje w jego wnętrzu, a jedynie na odwrót. Sprawdzam, jak :has() odwraca ten kierunek, czym różni się od zwykłych kombinatorów i gdzie ta nowa moc realnie kosztuje wydajność.