content-Visibility: la nouvelle propriété CSS qui améliore les performances d'affichage

Améliorez le temps de chargement initial en ignorant l'affichage du contenu hors écran.

La propriété content-visibility, lancée dans Chromium 85, pourrait être l'une des nouvelles propriétés CSS les plus efficaces pour améliorer les performances de chargement des pages. content-visibility permet au user-agent d'ignorer les tâches de rendu d'un élément, y compris la mise en page et la peinture, jusqu'à ce que cela soit nécessaire. Étant donné que l'affichage est ignoré, si une grande partie de votre contenu est hors écran, l'utilisation de la propriété content-visibility accélère le chargement initial de l'utilisateur. Cela permet également d'interagir plus rapidement avec le contenu à l'écran. Plutôt chouette.

démo avec des figures représentant les résultats d'un réseau
Dans la démonstration de notre article, l'application de content-visibility: auto à des zones de contenu fragmentées permet de booster les performances de rendu x7 lors du chargement initial. Lisez la suite pour en savoir plus.

Prise en charge des navigateurs

Navigateurs pris en charge

  • 85
  • 85
  • 124

Source

content-visibility repose sur les primitives de la spécification de conteneur CSS. Bien que content-visibility ne soit compatible qu'avec Chromium 85 pour le moment (et qu'il soit considéré comme un prototype utile pour Firefox), cette spécification est compatible avec la plupart des navigateurs récents.

Confinement CSS

L'objectif principal du confinement CSS est d'améliorer les performances d'affichage du contenu Web en fournissant une isolation prévisible d'une sous-arborescence DOM du reste de la page.

Fondamentalement, un développeur peut indiquer à un navigateur quelles parties de la page sont encapsulées en tant qu'ensemble de contenu, ce qui permet aux navigateurs de raisonner sur le contenu sans avoir à tenir compte de l'état en dehors de la sous-arborescence. Si vous savez quels bits de contenu (sous-arborescences) contiennent du contenu isolé, le navigateur peut prendre des décisions d'optimisation pour le rendu des pages.

Il existe quatre types de contenu CSS, chacun étant une valeur potentielle pour la propriété CSS contain, qui peut être combinée dans une liste de valeurs séparées par des espaces:

  • size: le confinement de la taille sur un élément garantit que la boîte de l'élément peut être disposée sans qu'il soit nécessaire d'examiner ses descendants. Cela signifie que nous pouvons potentiellement ignorer la mise en page des descendants si nous n'avons besoin que de la taille de l'élément.
  • layout: le confinement de la mise en page signifie que les descendants n'affectent pas la mise en page externe des autres zones de la page. Cela nous permet d'ignorer la mise en page des descendants si nous ne voulons pas simplement mettre en page d'autres zones.
  • style: le confinement du style garantit que les propriétés pouvant avoir des effets sur d'autres éléments que ses descendants n'échappent pas à l'élément (comme les compteurs). Cela nous permet d'ignorer potentiellement les calculs de style pour les descendants si nous ne voulons calculer que les styles sur d'autres éléments.
  • paint: le confinement de la peinture garantit que les descendants du conteneur ne s'affichent pas en dehors de ses limites. Rien ne peut déborder visiblement sur l'élément. Si un élément se trouve en dehors de l'écran ou n'est pas visible, ses descendants ne seront pas non plus visibles. Cela nous permet de ne pas peindre les descendants si l'élément est hors écran.

Omission de l'affichage avec content-visibility

Il peut être difficile de déterminer quelles valeurs de confinement utiliser, car les optimisations de navigateur ne se produisent que lorsqu'un ensemble approprié est spécifié. Vous pouvez tester les valeurs pour voir ce qui fonctionne le mieux ou utiliser une autre propriété CSS appelée content-visibility pour appliquer automatiquement le confinement nécessaire. content-visibility vous permet d'obtenir les meilleurs gains de performances possible avec le navigateur, avec un minimum d'effort de votre part en tant que développeur.

La propriété de visibilité sur le contenu accepte plusieurs valeurs, mais auto est celle qui améliore immédiatement les performances. Un élément comportant content-visibility: auto obtient le confinement des éléments layout, style et paint. Si l'élément se trouve en dehors de l'écran (et qu'il n'est pas pertinent pour l'utilisateur, les éléments pertinents sont ceux qui sont ciblés ou sélectionnés dans leur sous-arborescence), il obtient également le confinement de size (et arrête la peinture et le test de positionnement de son contenu).

Qu'est-ce que cela signifie ? En bref, si l'élément est en dehors de l'écran, ses descendants ne sont pas affichés. Le navigateur détermine la taille de l'élément sans tenir compte de son contenu et s'arrête là. La plupart du rendu, comme le style et la mise en page de la sous-arborescence de l'élément, sont ignorés.

Lorsque l'élément s'approche de la fenêtre d'affichage, le navigateur n'ajoute plus le confinement size et commence à peindre le contenu de l'élément et à effectuer un test de positionnement. Le rendu peut ainsi être effectué juste à temps pour être vu par l'utilisateur.

Remarque sur l'accessibilité

L'une des fonctionnalités de content-visibility: auto est que le contenu hors écran reste disponible dans le modèle d'objet de document et, par conséquent, dans l'arborescence d'accessibilité (contrairement à visibility: hidden). Cela signifie qu'il est possible de rechercher ce contenu sur la page et d'y accéder sans attendre le chargement ni sacrifier les performances de rendu.

À l'inverse, les éléments point de repère avec des caractéristiques de style telles que display: none ou visibility: hidden apparaissent également dans l'arborescence d'accessibilité lorsqu'ils sont hors écran, car le navigateur n'affiche pas ces styles tant qu'ils n'entrent pas dans la fenêtre d'affichage. Pour éviter que ces éléments ne soient visibles dans l'arborescence d'accessibilité et qu'ils ne s'encombrent pas, veillez également à ajouter aria-hidden="true".

Exemple: blog de voyages

Dans cet exemple, nous avons base notre blog de voyage sur la droite et appliquons content-visibility: auto aux zones fragmentées sur la gauche. Les résultats indiquent des temps d'affichage allant de 232 ms à 30 ms pour le chargement initial de la page.

Un blog de voyage contient généralement une série d'histoires composées de quelques images et d'un texte descriptif. Voici ce qui se passe dans un navigateur classique lorsqu'il accède à un blog de voyage:

  1. Une partie de la page est téléchargée à partir du réseau, avec toutes les ressources nécessaires.
  2. Le navigateur met en forme et met en page tout le contenu de la page, sans tenir compte de son visibilité pour l'utilisateur.
  3. Le navigateur revient à l'étape 1 jusqu'à ce que l'ensemble de la page et des ressources aient été téléchargées.

À l'étape 2, le navigateur traite l'ensemble du contenu à la recherche d'éléments susceptibles d'avoir changé. Elle met à jour le style et la mise en page des nouveaux éléments, ainsi que ceux qui ont pu changer à la suite de nouvelles mises à jour. Il s'agit d'un rendu. Cela prend du temps.

Capture d'écran d'un blog de voyage.
Exemple de blog de voyage. Voir la démonstration sur Codepen

Réfléchissez maintenant à ce qui se passe si vous placez content-visibility: auto sur chacune des articles du blog. La boucle générale est la même: le navigateur télécharge et affiche des fragments de la page. Cependant, la différence réside dans la quantité de travail effectuée à l'étape 2.

Avec la visibilité du contenu, elle applique un style et une mise en page à tous les contenus actuellement visibles par l'utilisateur (ils sont à l'écran). Toutefois, lors du traitement de l'histoire entièrement en dehors de l'écran, le navigateur ignore le rendu et n'applique que le style et la mise en page de la zone de l'élément elle-même.

Cette page se chargerait comme si elle contenait des histoires en plein écran et des zones vides pour chacune d'elles. Les performances sont nettement meilleures, avec une réduction attendue d'au moins 50% du coût de rendu lié au chargement. Dans notre exemple, nous constatons un temps de rendu de 232 ms à 30 ms. Les performances sont multipliées par sept.

Que devez-vous faire pour en profiter ? Tout d'abord, nous divisons le contenu en sections:

Capture d'écran annotée de la segmentation du contenu en sections avec une classe CSS.
Exemple de segmentation du contenu en sections avec la classe story appliquée pour recevoir content-visibility: auto. Voir la démonstration sur Codepen

Ensuite, nous appliquons la règle de style suivante aux sections:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

Spécifier la taille naturelle d'un élément avec contain-intrinsic-size

Pour profiter des avantages potentiels de content-visibility, le navigateur doit appliquer un confinement de la taille afin de s'assurer que les résultats d'affichage du contenu n'affectent en aucune façon la taille de l'élément. Cela signifie que l'élément s'affichera comme s'il était vide. Si l'élément n'a pas de hauteur spécifiée dans une mise en page de blocs standard, sa hauteur sera de 0.

Ce n'est peut-être pas idéal, car la taille de la barre de défilement va changer, car chaque article aura une hauteur différente de zéro.

Heureusement, CSS fournit une autre propriété, contain-intrinsic-size, qui spécifie effectivement la taille naturelle de l'élément si celui-ci est affecté par la structuration. Dans notre exemple, nous le définissons sur 1000px pour estimer la hauteur et la largeur des sections.

Cela signifie qu'il s'affiche comme s'il avait un seul enfant de dimensions de "taille intrinsèque". Ainsi, vos éléments div non dimensionnés occupaient toujours l'espace. contain-intrinsic-size sert de taille d'espace réservé au lieu du contenu affiché.

Dans Chromium 98 et les versions ultérieures, il existe un nouveau mot clé auto pour contain-intrinsic-size. Si elle est spécifiée, le navigateur se souviendra de la dernière taille affichée, le cas échéant, et l'utilisera à la place de la taille d'espace réservé fournie par le développeur. Par exemple, si vous avez spécifié contain-intrinsic-size: auto 300px, l'élément commencera avec un dimensionnement intrinsèque de 300px dans chaque dimension, mais une fois le contenu de l'élément affiché, il conservera la taille intrinsèque affichée. Toute modification ultérieure de la taille de rendu est également mémorisée. En pratique, cela signifie que si vous faites défiler un élément avec content-visibility: auto appliqué, puis que vous le faites de nouveau en dehors de l'écran, il conservera automatiquement sa largeur et sa hauteur idéales, et ne reviendra pas au dimensionnement de l'espace réservé. Cette fonctionnalité est particulièrement utile pour les utilisateurs à défilement infini, qui peuvent désormais améliorer automatiquement l'estimation du dimensionnement au fil du temps, à mesure que l'utilisateur explore la page.

Masquer du contenu avec content-visibility: hidden

Que se passe-t-il si vous souhaitez conserver le contenu non affiché, qu'il soit affiché ou non à l'écran, tout en tirant parti des avantages de l'état d'affichage mis en cache ? Saisissez content-visibility: hidden.

La propriété content-visibility: hidden vous offre les mêmes avantages de contenu non affiché et d'état de rendu mis en cache que content-visibility: auto hors écran. Toutefois, contrairement à auto, l'affichage ne commence pas automatiquement à l'écran.

Vous bénéficiez ainsi d'un contrôle accru, ce qui vous permet de masquer le contenu d'un élément pour l'afficher rapidement par la suite.

Comparez ce comportement à d'autres méthodes courantes pour masquer le contenu d'un élément:

  • display: none: masque l'élément et détruit son état de rendu. Cela signifie que le coût d'affichage de l'élément est aussi élevé que d'afficher un nouvel élément avec le même contenu.
  • visibility: hidden: masque l'élément et conserve son état de rendu. Cela ne supprime pas vraiment l'élément du document, car il (et sa sous-arborescence) occupe toujours de l'espace géométrique sur la page et l'utilisateur peut toujours cliquer dessus. Il met également à jour l'état de rendu chaque fois que cela est nécessaire, même lorsqu'il est masqué.

En revanche, content-visibility: hidden masque l'élément tout en conservant son état de rendu. Par conséquent, si des modifications doivent être effectuées, elles ne se produisent que lorsque l'élément est de nouveau affiché (c'est-à-dire lorsque la propriété content-visibility: hidden est supprimée).

content-visibility: hidden peut être utilisé lors de l'implémentation de défilements virtuels avancés et de la mesure de la mise en page. Elles sont également idéales pour les applications monopages (SPA). Les vues d'application inactives peuvent être laissées dans le DOM avec content-visibility: hidden appliqué pour empêcher leur affichage, mais conserver leur état mis en cache. La vue s'affiche ainsi rapidement lorsqu'elle est réactivée.

Effets sur l'interaction avec la peinture suivante (INP)

INP est une métrique qui évalue la capacité d'une page à répondre de manière fiable aux entrées utilisateur. La réactivité peut être affectée par les tâches excessives effectuées sur le thread principal, y compris le travail d'affichage.

Chaque fois que vous pouvez réduire la charge de travail d'affichage sur une page donnée, vous donnez au thread principal la possibilité de répondre plus rapidement aux entrées utilisateur. Cela inclut le rendu. L'utilisation de la propriété CSS content-visiblity, le cas échéant, peut réduire les tâches d'affichage, en particulier au démarrage, lorsque la plupart des tâches d'affichage et de mise en page sont effectuées.

La réduction du travail de rendu a un effet direct sur INP. Lorsque les utilisateurs tentent d'interagir avec une page qui utilise correctement la propriété content-visibility pour différer la mise en page et l'affichage des éléments hors écran, vous donnez au thread principal la possibilité de répondre aux tâches essentielles visibles par l'utilisateur. Cela peut améliorer l'INP de votre page dans certains cas.

Conclusion

Avec content-visibility et la spécification CSS Containment Spec, votre fichier CSS bénéficie directement d'améliorations intéressantes des performances. Pour en savoir plus sur ces propriétés, consultez: