Aider les navigateurs à optimiser avec la propriété CSS Contain

Publié: 2022-03-10
Résumé rapide ↬ La propriété CSS contain vous permet d'expliquer votre mise en page au navigateur, afin que des optimisations de performances puissent être effectuées. Cependant, cela a des effets secondaires en termes de mise en page.

Dans cet article, je vais vous présenter une spécification CSS qui vient de devenir une recommandation du W3C. La spécification CSS Containment définit une propriété unique, contain , et elle peut vous aider à expliquer au navigateur quelles parties de votre mise en page sont indépendantes et n'auront pas besoin d'être recalculées si une autre partie de la mise en page change.

Bien que cette propriété existe pour des raisons d'optimisation des performances, elle peut également affecter la mise en page de votre page. Par conséquent, dans cet article, je vais vous expliquer les différents types de confinement dont vous pouvez bénéficier, mais aussi les éléments auxquels vous devez faire attention si vous appliquez le confinement aux contain de votre site.

Le problème du recalcul de la mise en page

Si vous créez des pages Web simples qui n'ajoutent ni ne modifient dynamiquement des éléments après leur chargement à l'aide de JavaScript, vous n'avez pas à vous soucier du problème résolu par CSS Containment. Le navigateur n'a besoin de calculer votre mise en page qu'une seule fois, lors du chargement de la page.

Là où le confinement devient utile, c'est lorsque vous souhaitez ajouter des éléments à votre page sans que l'utilisateur ait besoin de la recharger. Dans mon exemple, j'ai créé une grande liste d'événements. Si vous cliquez sur le bouton, le premier événement est modifié, un élément flottant est ajouté et le texte est modifié :

Une liste d'éléments avec un bouton pour modifier une partie du contenu du premier élément
(Voir l'exemple initial sur CodePen)

Lorsque le contenu de notre boîte est modifié, le navigateur doit considérer que l'un des éléments peut avoir changé. Les navigateurs sont en général assez bons pour gérer cela, car c'est une chose courante. Cela dit, en tant que développeur, vous saurez si chacun des composants est indépendant et qu'un changement apporté à l'un n'affecte pas les autres, donc ce serait bien si vous pouviez le faire savoir au navigateur via votre CSS. C'est ce que le confinement et la propriété CSS contain vous donnent.

Plus après saut! Continuez à lire ci-dessous ↓

Comment le confinement aide-t-il ?

Un document HTML est une structure arborescente que vous pouvez voir lors de l'inspection de n'importe quel élément avec DevTools. Dans mon exemple ci-dessus, j'identifie un élément que je souhaite modifier à l'aide de JavaScript, puis j'apporte des modifications aux composants internes. (Cela signifie que je ne change que des choses à l'intérieur de la sous-arborescence pour cet élément de liste.)

DevTools avec l'élément de liste de l'élément en vedette développé pour voir les éléments à l'intérieur
Inspecter un élément de liste dans DevTools

L'application de la propriété contain à un élément indique au navigateur que les modifications sont étendues à la sous-arborescence de cet élément, de sorte que le navigateur puisse effectuer toutes les optimisations possibles, en sachant que rien d'autre en dehors de cet élément ne changera. Exactement ce qu'un navigateur particulier pourrait faire dépend du moteur. La propriété CSS vous donne simplement, en tant que développeur et expert de cette mise en page, la possibilité de le faire savoir.

Dans de nombreux cas, vous serez sûr d'aller de l'avant et de commencer à utiliser la propriété contain , cependant, les différentes valeurs s'accompagnent d'effets secondaires potentiels qu'il convient de comprendre avant d'ajouter la propriété aux éléments de votre site.

Utiliser le confinement

La propriété contain peut définir trois types de confinement différents :

  • layout
  • paint
  • size

Remarque : Il existe une valeur de style dans la spécification de niveau 2. Il a été supprimé du niveau 1, il n'apparaît donc pas dans la recommandation et n'est pas implémenté dans Firefox.

Mise en page

Le confinement de la mise en page apporte les plus grands avantages. Pour activer le confinement de mise en page, utilisez l'extrait de code suivant :

 .item { contain: layout; }

Lorsque le confinement de la mise en page est activé, le navigateur sait que rien en dehors de l'élément ne peut affecter la mise en page interne, et rien de l'intérieur de l'élément ne peut changer quoi que ce soit à la mise en page des choses à l'extérieur. Cela signifie qu'il peut effectuer toutes les optimisations possibles pour ce scénario.

Quelques choses supplémentaires se produisent lorsque le confinement de mise en page est activé. Ce sont toutes des choses qui garantissent que cette boîte et son contenu sont indépendants du reste de l'arbre.

La boîte établit un contexte de formatage indépendant . Cela garantit que le contenu de la boîte reste dans la boîte - en particulier, les flottants seront contenus et les marges ne s'effondreront pas à travers la boîte. C'est le même comportement que nous activons lorsque nous utilisons display: flow-root comme expliqué dans mon article "Comprendre la mise en page CSS et le contexte de formatage des blocs". Si un flotteur pouvait sortir de votre boîte, faisant circuler le texte suivant autour du flotteur, ce serait une situation où l'élément changeait la disposition des choses à l'extérieur, ce qui en faisait un mauvais candidat pour le confinement.

La boîte contenante agit comme le bloc contenant pour tous les descendants de position absolue ou fixe. Cela signifie qu'il agira comme si vous aviez utilisé position: relative sur la boîte que vous avez appliquée contain: layout .

La boîte crée également un contexte d'empilement . Par conséquent z-index fonctionnera sur cet élément, ses enfants seront empilés en fonction de ce nouveau contexte.

Si nous regardons l'exemple, cette fois avec contain: layout , vous pouvez voir que lorsque l'élément flottant est introduit, il ne dépasse plus le bas de la boîte. Voici notre nouveau contexte de formatage de bloc en action, contenant le flottant.

Une liste d'éléments, un élément flottant est contenu à l'intérieur des limites de la boîte parent
À l'aide de contenir : mise en page le flotteur est contenu (Voir l'exemple de confinement de mise en page sur CodePen)

Peindre

Pour activer le confinement de la peinture, utilisez les éléments suivants :

 .item { contain: paint; }

Lorsque le confinement de peinture est activé, les mêmes effets secondaires que ceux observés avec le confinement de mise en page se produisent : la boîte contenante devient un contexte de formatage indépendant, un bloc contenant pour les éléments positionnés et établit un contexte d'empilement.

Ce que fait le confinement de peinture est d'indiquer au navigateur que les éléments à l'intérieur du bloc contenant ne seront pas visibles en dehors des limites de cette boîte. Le contenu sera essentiellement coupé à la boîte.

Nous pouvons voir cela se produire avec un exemple simple. Même si nous donnons une hauteur à notre carte, l'élément flottant dépasse toujours du fond de la boîte, en raison du fait que le flotteur est retiré du flux.

Une boîte flottante sortant du fond d'une boîte contenant
Le flottant n'est pas contenu par l'élément de liste

Avec le confinement de la peinture activé, l'élément flottant est maintenant coupé à la taille de la boîte. Rien ne peut être peint en dehors des limites de l'élément contain: paint appliquée.

Une boîte avec une boîte flottante à l'intérieur qui a été coupée là où elle s'échappe de la boîte
Le contenu de la boîte est clippé à la hauteur de la boîte (Voir l'exemple de peinture sur CodePen)

Taille

Le confinement de la taille est la valeur la plus susceptible de vous causer un problème si vous n'êtes pas pleinement conscient de son fonctionnement. Pour appliquer le confinement de taille, utilisez :

 .item { contain: size; }

Si vous utilisez le confinement de la taille, vous indiquez au navigateur que vous connaissez la taille de la boîte et qu'elle ne changera pas. Cela signifie que si vous avez une boîte qui est automatiquement dimensionnée dans la dimension de bloc, elle sera traitée comme si le contenu n'avait pas de taille, donc la boîte se réduira comme si elle n'avait pas de contenu.

Dans l'exemple ci-dessous, je n'ai pas donné de hauteur au li ; ils ont également contain: size appliquée. Vous pouvez voir que tous les éléments se sont effondrés comme s'ils n'avaient aucun contenu, ce qui donne une liste très particulière !

Une liste d'éléments avec un bouton pour modifier une partie du contenu du premier élément
(Voir l'exemple de taille sur CodePen)

Si vous donnez une hauteur aux boîtes, alors la hauteur sera respectée lorsque vous utiliserez le paramètre contain: size . Seul, le confinement de la taille ne créera pas de nouveau contexte de formatage et ne contient donc pas de flottants et de marges comme le feront le confinement de la mise en page et de la peinture. Il est moins probable que vous l'utilisiez seul ; au lieu de cela, il est fort probable que vous l'appliqueriez avec d'autres valeurs de contain pour pouvoir obtenir le confinement le plus possible.

Valeurs abrégées

Dans la plupart des cas, vous pouvez utiliser l'une des deux valeurs abrégées pour tirer le meilleur parti du confinement. Pour activer le confinement de la mise en page et de la peinture, utilisez contain: content; , et pour activer tous les confinements possibles (en gardant à l'esprit que les éléments qui n'ont pas de taille s'effondreront alors), utilisez contain: strict .

La spécification dit:

contain: content est raisonnablement "sûr" pour être largement appliqué ; ses effets sont assez mineurs dans la pratique, et la plupart des contenus ne vont pas à l'encontre de ses restrictions. Cependant, comme il n'applique pas de confinement de taille, l'élément peut toujours répondre à la taille de son contenu, ce qui peut entraîner une invalidation de la mise en page pour remonter plus haut dans l'arborescence que souhaité. Utilisez contain: strict lorsque cela est possible, pour obtenir autant de confinement que possible. »

Par conséquent, si vous ne connaissez pas la taille des éléments à l'avance et comprenez le fait que les flottants et les marges seront contenus, utilisez contain: content . Si vous connaissez la taille des éléments en plus d'être satisfait des autres effets secondaires du confinement, utilisez contain: strict . Le reste dépend du navigateur, vous avez fait votre part en expliquant le fonctionnement de votre mise en page.

Puis-je utiliser le confinement maintenant ?

La spécification CSS Containment est désormais une recommandation du W3C, ce que nous appelons parfois une norme Web . Pour que la spécification arrive à ce stade, il fallait deux implémentations de la fonctionnalité que nous pouvons voir à la fois dans Firefox et Chrome :

Capture d'écran des informations de prise en charge du navigateur sur Confinement sur Puis-je utiliser
Prise en charge du navigateur pour le confinement (Source : Puis-je utiliser)

Comme cette propriété est transparente pour l'utilisateur, il est totalement sûr de l'ajouter à n'importe quel site, même si vous avez beaucoup de visiteurs dans des navigateurs qui ne la prennent pas en charge. Si le navigateur ne prend pas en charge le confinement, le visiteur obtient l'expérience qu'il obtient habituellement, ceux des navigateurs prenant en charge obtiennent des performances améliorées.

Je dirais que c'est une bonne chose à ajouter à tous les composants que vous créez dans une bibliothèque de composants ou de modèles, si vous travaillez de cette manière, il est probable que chaque composant est conçu pour être une chose indépendante qui n'affecte pas les autres éléments sur le page, faisant contain: content un ajout utile.

Par conséquent, si vous avez une page qui ajoute du contenu au DOM après le chargement, je vous recommande de l'essayer - si vous obtenez des résultats intéressants, faites-le moi savoir dans les commentaires !

Ressources associées

Les ressources suivantes vous donneront plus de détails sur la mise en œuvre du confinement et les avantages potentiels en termes de performances :

  • « La propriété CSS contain », documentation Web MDN
  • « Confinement CSS dans Chrome 52 », développeurs Google
  • "Module de confinement CSS niveau 1", recommandation du W3C
  • "Une introduction au confinement CSS", Manuel Rego Casasnovas