Six cartes sur un tableau de bord, six spinners, et ils n'apparaissent pas ensemble — ils apparaissent l'un après l'autre, comme des dominos, car chacun n'a commencé à charger qu'après que celui du dessus a terminé. C'est une cascade, et l'attente totale n'est pas la requête la plus lente, c'est la somme de toutes. use() et Suspense brisent la chaîne — mais la partie intéressante est la machinerie en dessous : ce que lance réellement un composant suspendu, et comment HTML qui arrive dans le désordre atterrit quand même au bon endroit.
Il y a une raison pour laquelle le parallax JavaScript semble toujours légèrement décalé — un peu détaché, comme si les couches nageaient un demi-frame derrière la page. Ce n'est pas du code bâclé. C'est parce que les événements de défilement atteignent votre JavaScript après que le navigateur a déjà peint le défilement. Le navigateur a déjà résolu ça une fois, en transformant les en-têtes collants en position: sticky. Les scroll-driven animations sont le même mouvement, appliqué à tous les effets liés au défilement d'un coup.
Pendant dix ans, animer une miniature en image hero signifiait une seule technique : mesurer l'élément avant, mesurer après, simuler la différence avec un transform, et lancer. FLIP. Chaque bibliothèque d'animation le fait, et chacune le paye en JavaScript sur le thread principal au pire moment possible. La View Transitions API déplace tout ce tour de passe-passe dans le navigateur — et depuis React 19.2 et Next.js 16, tout le contrat tient en un seul prop appelé name.
Dans l'article sur les micro-interactions, j'écrivais que transform et opacity s'animent sur le thread de composition, donc même une page lourde ne devrait pas saccader l'animation d'un bouton. C'est toujours vrai – avec une réserve que cet article-là passait sous silence : si le thread principal est bloqué par une longue tâche JS, l'animation risque de ne jamais avoir la chance de démarrer, car le handler de clic lui-même attend dans la file. L'INP est la métrique qui mesure exactement cet écart – et scheduler.yield() est l'un des rares moyens de réellement le combler.
Une liste de mille commentaires se rend lentement, alors vous vous tournez vers react-window – et en échange d'un scroll fluide, vous perdez Ctrl+F, l'impression de la page et en partie la navigation du lecteur d'écran, car les éléments hors de la fenêtre cessent d'exister physiquement dans le DOM. content-visibility résout le même problème autrement : les éléments restent dans le DOM, le navigateur se contente de sauter pour eux le travail coûteux de mise en page et de peinture tant qu'ils ne sont pas proches de la zone visible – et, chose surprenante, il peut les révéler temporairement quand vous y cherchez du texte.
Dans l'article sur l'accessibilité, une modale en display:none qui restait présente dans l'arbre d'accessibilité illustrait une erreur née d'une modale construite à la main sur des divs. La vraie question est : pourquoi fallait-il la construire à la main ? J'examine ce que le <dialog> natif et l'attribut popover offrent gratuitement – top layer, piège à focus, light dismiss – et où ces deux mécanismes divergent suffisamment pour que les confondre soit le chemin le plus court vers une interface inaccessible.