Accueil / Articles

Réorganisation du flux, redessin, composition : quel est le coût pour le navigateur de chaque modification CSS

Suivez le parcours d’HTML et CSS à travers DOM, CSSOM, l’agencement, le rendu graphique et la composition, et découvrez pourquoi les changements de largeur sont plus coûteux que ceux des couleurs, ainsi que comment éviter les problèmes d’agencement.

Éditeur : REACTAPP.TOP16 min de lecture3720 mots

Sources: Browser Rendering Pipeline Explained: From HTML to Pixels + Reflow vs Repaint

Une seule ligne de balisage, comme un titre, peut sembler anodine, mais le navigateur effectue une longue série d’opérations avant qu’elle ne devienne des pixels à l’écran. Comprendre cette chaîne de transformations vous permet de répondre à des questions pratiques : pourquoi redimensionner un élément peut ralentir une page, pourquoi les animations sont généralement écrites avec transform, pourquoi un seul changement peut avoir des effets sur des dizaines d’autres éléments, et pourquoi une manipulation intensive du DOM entraîne une interface instable. Ce guide passe en revue chaque étape du pipeline de rendu, puis utilise ce modèle pour expliquer la différence entre le reflow et le repaint ainsi que les bonnes pratiques permettant de maintenir une vitesse d’affichage élevée.

<h1>Hello World</h1>

Un aperçu du pipeline

En son essence, le pipeline de rendu est le processus qui transforme trois types d’entrées – le balisage, les styles et les scripts – en une image que l’écran peut afficher.

HTML + CSS + JavaScript
          ↓
       Pixels
          ↓
       Screen

Découpée en ses différentes étapes, la séquence ressemble à peu près à ceci :

Parse HTML
   ↓
Build DOM
   ↓
Parse CSS
   ↓
Build CSSOM
   ↓
Create Render Tree
   ↓
Calculate Styles
   ↓
Layout / Reflow
   ↓
Paint / Repaint
   ↓
Composite
   ↓
Pixels on Screen

Lorsque les gens parlent de la vitesse à laquelle une page affiche son premier contenu visible, ils désignent généralement cette séquence comme le Critical Rendering Path. Il convient de se rappeler qu’il s’agit d’un modèle, et non d’une spécification propre à un moteur en particulier. Chrome, Firefox et Safari implémentent ces étapes différemment, et dans les mises à jour ultérieures, ils sautent certaines étapes dès lors qu’ils peuvent prouver que ce travail est inutile. Ce modèle reste suffisamment précis pour analyser les performances, ce qui est essentiel dans le travail quotidien sur l’interface utilisateur.

Étape 1 : analyse de l’HTML pour le DOM

Tout commence avec le document HTML retourné par le serveur, par exemple une petite page contenant un titre et un paragraphe :

<!DOCTYPE html>
<html>
  <body>
    <h1>Hello World</h1>
    <p>Welcome to my website.</p>
  </body>
</html>

Le analyseur lit ce marquage et génère le Document Object Model, un arbre de nœuds dans lequel chaque élément et chaque portion de texte a une place définie. L’arbre correspondant au document ci-dessus ressemble à ceci :

HTML

<html>
  │
  └── body
       │
       ├── h1
       │    └── "Hello World"
       │
       └── p
            └── "Welcome..."

Le DOM capture ce que contient le document ainsi que sa structure hiérarchique. C’est également l’interface avec laquelle interagissent vos scripts ; ainsi, une appelation comme celle ci-dessous parcourt cet arbre pour trouver un nœud :

document.querySelector("h1");

L’analyse s’effectue de manière incrémentale. Le navigateur ne wait pas que le fichier soit entièrement chargé avant de commencer à créer des nœuds, c’est pourquoi une page longue peut commencer à s’afficher tandis que le reste du contenu est encore en train d’arriver.

Étape 2 : analyse du CSS en CSSOM

La structure seule ne dit rien sur l’apparence. Pour cela, le navigateur a besoin des feuilles de style, comme ces deux règles simples :

h1 {
  color: blue;
  font-size: 32px;
}

p {
  color: gray;
}

Le CSS est analysé pour former une deuxième structure, le CSS Object Model. Une façon utile de distinguer ces deux structures réside dans la question à laquelle chacune répond :

DOM
 ↓
"What exists on the page?"

CSSOM
 ↓
"How should those things look?"

Le rendu a besoin des réponses fournies par les deux structures. C’est aussi pour cette raison que les feuilles de style entravent le rendu.

Étape 3 : combiner les deux structures en un arbre de rendu

Lorsque le DOM et le CSSOM sont prêts, le navigateur les fusionne pour former un arbre de rendu.

        DOM
         +
       CSSOM
         ↓
    Render Tree

L’arbre de rendu ne contient que ce qui sera effectivement affiché, ainsi que les styles qui s’y appliquent. Prenons ce fragment :

<div>
  <h1>Hello</h1>
  <p>World</p>
</div>

Après cette fusion, on peut l’imaginer comme un arbre de boîtes visibles portant leurs informations de style :

Render Tree

div
│
├── h1
│   ├── font-size: 32px
│   └── color: blue
│
└── p
    └── color: gray

Tout élément qui ne participe pas à l’affichage est ignoré. Un élément avec display: none n’a absolument aucune entrée, ce qui diffère de visibility: hidden : un élément caché occupe toujours de l’espace, il reste donc dans l’arborescence et participe encore au rendu.

Étape 4 : calcul des styles calculés

Ensuite, le navigateur détermine le style calculé final pour chaque élément qui sera affiché. Les feuilles de style réelles contiennent des règles superposées comme celles-ci :

.card {
  width: 300px;
}

.card p {
  font-size: 16px;
}

Pour chaque élément, le moteur doit répondre successivement à trois questions :

Which rules apply?
        ↓
Which rule wins?
        ↓
What is the final computed style?

Y répondre signifie appliquer toutes les règles de résolution du CSS :

  • la cascade
  • l’héritage des éléments parents
  • la spécificité du sélecteur
  • la conversion en valeurs calculées
  • les styles dépendant des requêtes médias

Le résultat est un ensemble de propriétés définies pour chaque élément :

DOM + CSSOM
     ↓
Style Calculation
     ↓
Computed Styles

Étape 5 : mise en page, où la géométrie est déterminée

À ce stade, le navigateur sait ce qu’il doit afficher et à quoi cela doit ressembler. Ce qu’il ne sait pas encore, c’est où chaque élément se trouve et quelle est sa taille. C’est là que intervient la mise en page, qui transforme une zone de visualisation en un ensemble de boîtes positionnées :

Viewport
┌────────────────────────────┐
│                            │
│   Header                   │
│                            │
├──────────────┬─────────────┤
│ Sidebar      │ Content     │
│              │             │
│              │             │
└──────────────┴─────────────┘

Pendant la mise en page, le moteur calcule, pour chaque boîte de l’arbre de rendu :

  • la largeur et la hauteur
  • la position
  • les marges et les espaces intérieurs
  • la relation de chaque boîte avec ses voisins et ses ancêtres
  • la géométrie globale de la page

MDN résume cette étape comme la détermination de la taille et de l’emplacement de chaque nœud dans l’arbre de rendu. Comme les boîtes dépendent les unes des autres, la mise en page constitue un problème lié à l’ensemble de l’arbre plutôt qu’à chaque élément individuellement.

Refonte : exécution à nouveau du rendu

La première étape de traitement géométrique est simplement appelée rendu. Toute étape ultérieure déclenchée par un changement est généralement désignée sous le nom de refonte, et certaines équipes utilisent l’expression informelle « relayout » pour désigner la même chose :

Layout
  ↓
Initial calculation

Reflow / ReLayout
  ↓
Subsequent layout calculation

Le reste de ce guide utilise le terme « refonte », car c’est celui que l’on trouve dans la plupart des discussions sur les performances et les outils correspondants.

Qu’est-ce qui déclenche une refonte ?

Commençons par une boîte ayant une largeur fixe :

.box {
  width: 200px;
}

Un script modifie ensuite cette largeur en temps de exécution :

box.style.width = "500px";

Cette seule affectation soulève une série de questions auxquelles le navigateur doit répondre avant de pouvoir afficher l’image suivante :

The box changed width.

What else is affected?
Does its parent change?
Do neighboring elements move?
Does the text wrap differently?
Does the height change?
Does the entire layout need recalculation?

Une partie ou la totalité de la page peut donc nécessiter une nouvelle étape de rendu, après quoi les étapes suivantes seront également exécutées :

Change width
    ↓
Style recalculation
    ↓
Layout / Reflow
    ↓
  Paint
    ↓
Composite

Propriétés qui affectent la géométrie

Toute propriété qui influence la taille ou la position peut entraîner des modifications de mise en page. Les principaux suspects sont :

width
height
margin
padding
top
left
right
bottom
font-size

Changer l’une d’entre elles peut déplacer ou redimensionner l’élément lui-même, ainsi que potentiellement tout ce qui se trouve autour de lui. Par exemple, les deux mises à jour suivantes peuvent forcer le navigateur à recalculer la mise en page :

element.style.width = "500px";
element.style.marginLeft = "100px";

font-size figure sur cette liste car la taille du texte modifie la hauteur de ligne et l’ajustement automatique, ce qui affecte à son tour la hauteur du bloc contenant et, par conséquent, la position de tout ce qui suit.

Pourquoi le reflow est coûteux

Considérez une structure de page typique avec plusieurs zones et du contenu imbriqué :

Page
│
├── Header
├── Navigation
├── Sidebar
├── Main Content
│    ├── Card
│    ├── Card
│    ├── Card
│    └── Table
└── Footer

Si un élément situé en haut devient plus grand, chaque carte, le tableau et le pied de page en dessous peuvent avoir besoin de nouvelles coordonnées. Un seul changement géométrique peut se propager à une grande partie de l’arborescence :

One Geometry Change
        ↓
Layout Recalculation
        ↓
Many Elements Recalculated
        ↓
      Paint
        ↓
    Composite

Cette diffusion rend coûteuse le travail de mise en page inutile, surtout lorsqu’elle se répète pendant une animation ou un glisser-déposer.

Étape 6 : peinture

Lorsque ces trois éléments sont définis, le navigateur peut commencer à générer des pixels :

What to display
       +
Where to display it
       +
How it should look

Peinture transforme les boîtes positionnées en opérations de dessin, puis finalement en pixels. Le contenu peint comprend :

  • le texte
  • les couleurs et les arrière-plans
  • les bordures
  • les ombres
  • les images
  • toute autre décoration visible
Layout
  ↓
Paint
  ↓
Pixels

MDN décrit la peinture comme l’étape qui convertit les boîtes issues de la mise en page en pixels réels à l’écran.

Nouvelle peinture : nouveaux pixels, même géométrie

Une nouvelle peinture est nécessaire lorsque un élément a l’air différent mais occupe exactement la même place. Changer la couleur du texte en est un exemple classique :

color: red;

Une nouvelle couleur n’a aucun effet sur l’un ou l’autre des éléments suivants :

Width
Height
Position
Layout relationships

Ainsi, le navigateur peut ignorer complètement l’agencement et emprunter un chemin plus court :

Style Recalculation
       ↓
Paint / Repaint
       ↓
   Composite

Reflow versus repaint côte à côte

Cette distinction constitue le fondement de la plupart des conseils concernant les performances de rendu, il est donc utile d’expliquer précisément chacun des aspects.

Le reflow recalcule la géométrie

Un reflow signifie que la taille ou la position d’au moins un élément doit être recalculée. Définir une largeur en est l’exemple typique :

element.style.width = "500px";

La chaîne complète d’étapes s’exécute alors :

Change
  ↓
Style
  ↓
Layout / Reflow
  ↓
Paint
  ↓
Composite

Le repaint ne fait que redessiner l’apparence

Un repaint signifie que l’élément a un aspect différent, mais aucune géométrie n’a besoin d’être rec calculée. Définir une couleur suffit pour le déclencher :

element.style.color = "red";

L’agencement est exclu de cette chaîne :

Change
  ↓
Style
  ↓
Paint / Repaint
  ↓
Composite

Réduits à une seule ligne chacun :

RELayout / Reflow
→ Geometry changes
Repaint
→ Visual appearance changes

Un bouton qui change de largeur ou de couleur

Imaginez un simple bouton d’appel à l’action :

┌─────────────────────┐
│       Buy Now       │
└─────────────────────┘

Supposons que sa largeur change de la première valeur à la deuxième :

width: 200px;
width: 400px;

Le bouton occupe désormais deux fois plus d’espace horizontal, ce qui peut pousser les éléments voisins sur le côté ou provoquer un saut de ligne. Il s’agit d’un changement géométrique, ce qui amène le navigateur à refaire son affichage puis à le redessiner :

Width changes
     ↓
Geometry changes
     ↓
  Reflow
     ↓
  Repaint

Supposons maintenant que seule la couleur d’arrière-plan change :

background-color: blue;

Le bouton conserve sa taille et sa position exactes, seuls ses pixels changent :

Color changes
     ↓
Geometry unchanged
     ↓
  Repaint

La relation est unidirectionnelle

Lorsque le layout change, les éléments se retrouvent à de nouvelles positions, et ces nouvelles positions nécessitent de nouveaux pixels :

Layout changes
     ↓
Browser needs new pixels
     ↓
   Paint

En bref, un refonte est généralement suivi d’un redessin :

Reflow
   ↓
Usually followed by
   ↓
Repaint

Le principe inverse n’est pas valable. Une nouvelle mise à l’écran peut avoir lieu spontanément, sans aucune opération de mise en page :

Repaint
   ↓
Does NOT necessarily require
   ↓
Reflow

Étape 7 : composition des calques dans une frame

Les moteurs modernes ne peignent pas toujours toute la page en une seule image plate. Ils peuvent diviser le contenu en calques distincts et les assembler lors d’une étape de composition finale :

Layer 1
   +
Layer 2
   +
Layer 3
   ↓
Composite
   ↓
Final Frame

Une page peut, par exemple, disposer d’un calque d’arrière-plan, d’une carte sur son propre calque et d’un élément animé sur un troisième calque :

┌──────────────────────┐
│ Background Layer     │
│                      │
│   ┌──────────────┐   │
│   │ Card Layer   │   │
│   └──────────────┘   │
│                      │
│   ┌──────────────┐   │
│   │ Animation    │   │
│   └──────────────┘   │
└──────────────────────┘

Le composant empile ces calques pour générer chaque frame. Certains éléments peuvent être promus à leur propre calque, et dans des cas appropriés, les navigateurs confient la composition au GPU. Une modification qui se contente de déplacer ou de mélanger un calque existant peut alors être appliquée sans avoir à recalerquer son contenu.

Pourquoi transform est la valeur par défaut pour les mouvements

Voici un effet de survol qui déplace une boîte en animant la propriété left, en partant de zéro :

.box {
  left: 0;
}

et qui se termine à 100 pixels vers la droite :

.box:hover {
  left: 100px;
}

Puisque left fait partie de la position de l’élément dans le layout, chaque étape de la transition entraîne une mise à jour du layout ainsi qu’un redessin. Ce même mouvement visuel peut être réalisé à l’aide d’une transformation :

.box {
  transform: translateX(0);
}

.box:hover {
  transform: translateX(100px);
}

Une transformation déplace l’élément déjà dessiné sans modifier sa boîte de layout, permettant ainsi au navigateur de gérer toute l’animation dans le composant, sans mise à jour de layout ni redessin à chaque frame. opacity présente des propriétés similaires et constitue le choix habituel pour les effets de fondu. Considérez cela comme une règle forte plutôt que comme une loi absolue. Le fait qu’une transformation reste bien gérée par le composant dépend de l’élément, des autres styles appliqués, de la manière dont les couches sont organisées et du moteur spécifique utilisé.

Quelles étapes une modification déclenche réellement

Pour la plupart des mises à jour de style, les opérations se déroulent le long d’une des deux branches après le rec calcul du style :

                    Change
                      ↓
              Recalculate Style
                      ↓
              ┌───────┴───────┐
              ↓               ↓
           Layout           No Layout
              ↓               │
            Paint             │
              ↓               ↓
              └───────┬───────┘
                      ↓
                  Composite
                     ↓
                  Screen

Moins les mises à jour fréquentes touchent d’étapes coûteuses, plus il est facile de maintenir une rendu fluide. MDN décrit la même séquence : rec calcul du style, puis mise en page, puis affichage, et composition là où cela est applicable. Les modifications de transform ou opacity sur une couche composée peuvent même sauter l’étape d’affichage, qui est la voie la moins coûteuse de toutes.

Le budget temporel par frame : environ 16,67 ms

La plupart des écrans se mettent à jour environ 60 fois par seconde, ce qui laisse un temps fixe pour chaque frame :

1 second
   ÷
60 frames
   ≈
16.67ms per frame

En d’autres termes, pour atteindre 60 FPS, le navigateur dispose d’environ autant de temps par frame :

16.67ms

Ce budget est partagé par tout ce qui doit se produire avant que la frame ne soit affichée : votre JavaScript, le calcul des styles, l’agencement, la mise en page graphique ainsi que les tâches internes du navigateur. Lorsque la consommation totale dépasse cette limite, la frame est supprimée et l’utilisateur observe des interruptions dans l’affichage :

16.67ms
   ↓
Exceeded
   ↓
Frame missed
   ↓
 Jank

Cet effet est particulièrement visible dans les interactions qui génèrent des frames de manière continue :

  • le défilement
  • les animations
  • le glisser-déposer
  • la modification de la taille des fenêtres ou des panneaux
  • les tableaux de bord qui mettent à jour de nombreuses valeurs en même temps

MDN souligne le même point : le calcul des styles, l’agencement et la mise en page graphique doivent tous tenir dans le budget alloué aux frames pour que l’animation paraisse fluide.

Problèmes d’agencement : lectures qui imposent un agencement synchrone

Une méthode particulièrement courante de gaspillage du budget des frames semble inoffensive dans le code. Le fragment suivant définit une largeur, lit une taille, définit une hauteur et lit à nouveau :

element.style.width = "500px";
console.log(element.offsetWidth);
element.style.height = "500px";
console.log(element.offsetHeight);

Le schéma qu’il génère est une alternance d’écritures et de lectures :

Write
 ↓
Read layout
 ↓
Write
 ↓
Read layout

Normalement, le navigateur diffère le calcul du rendu jusqu’au moment de dessiner la prochaine frame, ce qui permet de traiter plusieurs modifications de style en une seule passe. Cependant, des propriétés comme offsetWidth et offsetHeight doivent retourner les valeurs actuelles. Lire une de ces propriétés immédiatement après une écriture force le moteur à valider synchroniquement et sur-le-champ tout le travail de mise en forme et de style en attente. Si cela se produit à plusieurs reprises, souvent à l’intérieur d’une boucle sur de nombreux éléments, on obtient un layout thrashing : de nombreuses passes complètes de mise en forme alors qu’une seule aurait suffi.

La solution consiste à regrouper les opérations de manière à ce que toutes les lectures aient lieu en premier et toutes les écritures par la suite :

Bad:
Write
Read
Write
Read
Write
Read

Better:
Read
Read
Read
Write
Write
Write

La manière de restructurer le code dépend de l’application, mais le principe reste toujours le même : ne pas obliger le navigateur à recalculer l’affichage plus souvent que nécessaire. Le blog propose un examen approfondi de le problème du layout thrashing et des collections DOM en temps réel si vous souhaitez davantage d’exemples de recalculs forcés.

Techniques pratiques pour un rendu moins coûteux

Animer la transformation et l’opacité

Au lieu de déplacer un élément à l’aide d’une propriété d’affichage comme ceci :

left: 100px;

préférez utiliser une transformation adaptée au design :

transform: translateX(100px);

Pour faire disparaître et réapparaître un élément progressivement, alternez entre ces deux valeurs :

opacity: 0;
opacity: 1;

c’est généralement une meilleure option que d’animer des propriétés qui affectent l’affichage.

Réduire au minimum les modifications du DOM

Chaque mutation du DOM peut entraîner davantage de tâches à exécuter par le navigateur. Ajouter des nœuds les uns après les autres de cette manière :

element.appendChild(...);
element.appendChild(...);
element.appendChild(...);

est souvent mieux remplacé par la création du nouveau contenu en dehors du document (un DocumentFragment, par exemple) et son insertion en une seule fois. Plus le DOM est grand et complexe, plus chaque modification évitable coûte cher.

Mises à jour en lot plutôt qu’en alternance

Le code qui alterne les mises à jour avec des tâches de mise en page aboutit à une séquence comme celle-ci :

Update
 ↓
Layout
 ↓
Update
 ↓
Layout
 ↓
Update
 ↓
Layout

L’objectif est de fournir au navigateur un ensemble de modifications qu’il peut traiter en même temps :

Update
Update
Update
 ↓
Browser processes the changes

Pour les animations et autres opérations visuelles à haute fréquence, requestAnimationFrame() planifie vos mises à jour pour qu’elles s’exécutent juste avant que le navigateur ne rende l’image suivante, ce qui les aligne avec le cycle de rendu au lieu de s’y opposer.

Ne pas animer les propriétés de mise en page

Les propriétés qui modifient la géométrie ne sont pas adaptées à des effets exécutés à chaque frame :

width
height
margin
padding
top
left
right
bottom
font-size

Chacune d’elles peut déclencher une mise à jour de la mise en page. Lorsque le résultat visuel le permet, animez plutôt celles-ci :

transform
opacity

Réserver de l’espace pour les images

Une balise d’image sans dimensions ne permet pas au navigateur de savoir combien d’espace laisser :

<img src="image.jpg">

Lorsque le fichier arrive et que sa taille réelle est connue, le contenu environnant se déplace et la mise en page est recalculée. Déclarer à l’avance la taille intrinsèque évite cela :

<img
  src="image.jpg"
  width="800"
  height="600"
  alt="Example"
/>

Un CSS aspect-ratio permet d’obtenir le même effet pour les images réactives. Dans les deux cas, le navigateur peut réserver la boîte appropriée avant le chargement de l’image, ce qui empêche tout décalage visible de la mise en page.

Mesurer avant d’optimiser

Toute répeinture ou itération de mise en page n’est pas un problème qui mérite d’être résolu ; les moteurs sont fortement optimisés et gèrent la plupart de ces tâches rapidement. Fondez vos efforts sur des preuves grâce à une boucle simple :

Performance Problem
       ↓
    Measure
       ↓
Find Bottleneck
       ↓
    Optimize
       ↓
 Measure Again

Le panneau Performance dans Chrome DevTools enregistre un chronogramme qui montre :

  • L’exécution du JavaScript
  • Le rec calcul des styles
  • La mise en page
  • La répeinture
  • Le travail de composition
  • Les tâches longues
  • Le timing par frame

Résolvez le goulot d’étranglement réellement identifié par le profil, et non simplement le code qui semble coûteux à première vue.

Tout le processus en une seule image

Assemblé de bout en bout, le parcours du fichier source à l’écran se présente comme suit :

                HTML
                  │
                  ↓
             Parse HTML
                  │
                  ↓
                 DOM
                  │
                  │
CSS ──→ Parse CSS ──> CSSOM
                  │
                  ↓
          DOM + CSSOM
                  │
                  ↓
             Render Tree
                  │
                  ↓
          Style Calculation
                  │
                  ↓
           Layout / Reflow
                  │
                  ↓
            Paint / Repaint
                  │
                  ↓
             Composite
                  │
                  ↓
           Pixels on Screen

Et lorsque quelque chose change après la première affichage, le point de décision clé est de déterminer si la géométrie en est affectée :

CSS / DOM Change
       ↓
Style Recalculation
       ↓
Does geometry change?
       │
    ┌──┴──┐
   YES    NO
    │      │
    ↓      ↓
 Layout   Paint
    │      │
    └──┬───┘
       ↓
   Composite
       ↓
     Screen

Points clés

Trois brefs résumés couvrent l’essentiel. Le reflow est la étape coûteuse :

RELayout / Reflow
        ↓
Changes geometry
        ↓
Width / Height / Position / Layout
        ↓
Usually leads to Paint

Le repaint est la étape moins chère :

     Repaint
        ↓
Changes appearance
        ↓
Color / Background / Shadow / etc.
        ↓
Doesn't necessarily require Layout

Et pour l’animation, le choix de la propriété détermine largement le coût :

Layout properties
    ↓
Potentially expensive

transform + opacity
    ↓
Often better for smooth animations

Vous n’avez pas besoin de connaître les détails internes de chaque moteur, mais vous devez être capable de suivre le processus général :

HTML
 ↓
DOM

CSS
 ↓
CSSOM

DOM + CSSOM
 ↓
Render Tree
 ↓
Style
 ↓
Layout
 ↓
Paint
 ↓
Composite
 ↓
Pixels

Avec ce modèle en tête :

  • Les changements de géométrie tels que width déclenchent d’abord le reflow puis le repaint ; les changements d’apparence tels que color nécessitent généralement uniquement un repaint.
  • transform et opacity permettent souvent de sauter l’étape de mise en page et du dessin, c’est pourquoi ils conviennent bien à l’animation.
  • Mélanger les écritures dans le DOM avec des lectures de mise en page provoque des problèmes de performance ; il faut donc effectuer les lectures en groupe avant les écritures.
  • Les images doivent indiquer leurs dimensions ou leur rapport d’aspect, et toute optimisation doit commencer par un profilage dans les DevTools.
  • Le navigateur effectuera toujours le travail réel pour transformer du code en pixels. L’objectif n’est pas d’éliminer ce travail, mais de ne pas en demander plus que ce dont la page a réellement besoin.

    Lectures complémentaires