Corrélation entre le temps de rendu et la complexité CSS

On en a parlé plusieurs fois. Le temps de reflow d’un navigateur est dépendant de la complexité des feuilles de style, et particulièrement de la complexité des sélecteurs CSS.

Google Page Speed y fait référence mais si vous voulez être convaincus il faut aller voir la présentation de Steve Souders aux conférences Velocity 2009. À l’écran 75 on trouve un graphique qui vérifie la corrélation entre le nombre de règles CSS, le nombre de sélecteurs complexes, et le temps nécessaire au reflow.

perf sélecteurs css

Il y a trop de choses en jeu pour tirer des conclusions fermes, mais une corrélation est des plus probable. Bref, écrémez vos CSS et simplifiez vos sélecteurs. Si en plus vous limitez le nombre de noeuds DOM et la profondeur moyenne, vous toucherez probablement le jackpot en terme de performance de rendu.

Pour vous aider Google Page Speed permet de repérer les sélecteurs potentiellement les plus coûteux, et ceux qui ne servent à rien dans la page en cours.

9 réflexions au sujet de « Corrélation entre le temps de rendu et la complexité CSS »

  1. Louis

    Aurais-tu quelques chiffres qui mettraient en valeur l’incidence de la qualité du CSS sur les performances de la page ? Je me demande dans quelle mesure il est intéressant d’optimiser le CSS.

  2. Éric

    @Nerocro: tous les liens sont là en suivant les différents billets sur le thème « sélecteurs css » (le second lien du présent billet) mais pour faire plus simple :
    - https://developer.mozilla.org/en/Writing_Efficient_CSS
    - http://blog.archive.jpsykes.com/153/more-css-performance-testing-pt-3/ (les graphes ont l’air d’être morts mais avec un peu de chances ils vont revenir)
    - http://code.google.com/intl/fr/speed/page-speed/docs/rendering.html#UseEfficientCSSSelectors

    @Louis:

    Pas beaucoup de chiffres, c’est trop dépendant de la CSS et de la page.

    On sait toutefois que les expressions et les filter ralentissent la page avec des délais de l’ordre de 100ms, ce qui est déjà pas mal. On sait aussi que la phase de rendu est fortement impactée par la complexité et l’écriture des CSS, et ça se joue à chaque reflow (cf graphique plus haut).

    Google et Steve Souders ont l’air de beaucoup se focaliser sur les CSS en ce moment. Je n’ai pas plus d’infos à apporter pour ma part malheureusement. Disons que c’est beaucoup moins simple à (dé)montrer que les systèmes de cache ou de requêtes HTTP, donc il reste à croire sur paroles qu’ils ont effectivement obtenu de bons résultats.

    Je crois que Nicole Sullivan travaille un peu là dessus, à refaire des CSS plus légères pour améliorer les perfs. Si ça vous intéresse je peux tenter de lui poser quelques questions et publier ça ici.

  3. Louis

    @Éric : merci pour les précisions. Je suis tout à fait interessé par des données chiffrées car on parle beaucoup de « CSS légères » en ce moment, mais j’aimerais savoir s’il est pertinent de consacrer du temps à revoir ses CSS.

    Sur un petit appareil type iPhone, je peux imaginer que l’on ai quelque chose à gagner de relativement important. En revanche, sur un ordinateur de bureau, je suis perplexe. J’aimerais quelques graphs comparitifs, sur des exemples types (page Amazon complexe, blog WordPress standard, page HTML simple).

  4. Ben S.

    Je comprend complètement le concept de « CSS légère », ça parait évident qu’alléger la CSS va améliorer les performances d’affichage.
    Cependant, en tant que développeur et intégrateur web, ça me met face au dilemne suivant :
    « Ecrire une CSS légère », semble impliquer qu’un CSS ne doit comporter que des règles manipulant les noeuds de la page en cours. C’est ce que j’en déduis en constatant que Google page speed et YSlow calculent le nombre d’instructions concernant des noeuds inexistants dans la page en cours (chose que j’ai toujours trouvé inutile, puisque mes CSS ne servent pas que pour 1 seule page).
    Or, une des bonnes pratiques conseillée pour optimiser les performances est qu’il ne faut utiliser qu’un seul fichier CSS pour éviter de télécharger pleins de petits fichiers…
    Personnellement, pour mon site, j’ai rédigé une 1 grosse CSS qui sait manipuler toutes les pages. Comme ça, dès la première visite, toutes les instructions CSS sont téléchargées et mises en cache pour le restant des pages.
    Mais s’il ne faut utiliser que des instructions relatives aux composants de chaque page, cela signifie qu’il faut rédiger 1 CSS pour la structure de la page, ainsi qu’une CSS pour chaque type de page. Dans ce cas, on perd l’avantage du fait que les feuilles de styles sont mises en cache : à chaque page visitée, le navigateur du visiteur doit télécharger une nouvelle CSS…

    Est-ce moi qui suit tordu ou bien vous êtes-vous aussi fait ce raisonnement ? Comment gérez vous ce genre de problématique pour des gros sites ?

  5. Éric

    Récupérer les déclarations inutiles d’une CSS permet surtout de repérer le code mort, celui qui est resté mais qui ne sert plus pour aucune page. Sinon, si réellement une grosse partie de la CSS n’est utilisée que sur une partie du site, ça peut valoir le coup de faire deux CSS séparées : chaque page continue à ne charger qu’une seule CSS, mais pas la même.

    La reflexion que vous menez est la bonne, mais savoir quand faire une seule CSS et quand faire une CSS par type de page, ça dépend de votre traffic, de vos CSS, de vos statistiques, etc. Difficile de répondre de manière générale.

  6. Ben S.

    Je comprends bien qu’il n’y ait pas de réponse toute faite pour pouvoir choisir telle ou telle façon de gérer les CSS. Mais je trouve en théorie dommage de faire télécharger 1 CSS par type de page alors que justement, un des intérêts majeurs de xHTML/CSS est de pouvoir mettre la CSS en cache une bonne fois pour toutes (mais c’est la théorie).

    Bref, comme je suis « webmaster » d’un seul mais gros site, je pense beaucoup à l’aspect maintenance. Et je ne me vois pas du tout faire 1 grosse CSS par section contenant à chaque fois les mêmes instructions pour tout l’entourage et la structure du site : seule la partie centrale change beaucoup selon le type de contenu (annuaire, magazine, agenda, fiche technique, lexique, boutique…).

    Si je veux donc faire des CSS « légères » et éviter de tout faire en 1 seul fichier, je pense finalement que je n’ai pas d’autre choix que d’appeler 2 CSS : template.css d’environ 10 à 20Ko et ensuite, 1 CSS par type de contenu (article.css, annuaire.css, agenda.css…).
    Sachant qu’on tourne à environ 160.000 visiteurs uniques par mois en moyenne, et sachant qu’actuellement j’utilise 2 feuilles CSS : une reset.css de 3Ko et surtout une CSS géante de 75Ko et 2800 lignes comprenant quasiment toutes les instructions du site (quelque soit le contenu central), je pense que scinder mes CSS ne pourra être que bénéfique, je me trompe ?

    Question (peut-être idiote) : les reflow sont-ils encore plus lents lorsqu’ils sont générés par 2 instructions se trouvant dans des CSS différentes ou non ?
    Exemple : dans la CSS template, j’indique un style par défaut pour mon h1{color:#777; font-size:1.5em}, puis dans ma CSS de type article, j’indique h1 {color:#FFF;background-color:red;padding:0 5px;}.
    (je sais que je vais déjà perdre un peu de temps à faire 2 requêtes HTTP différentes…).

  7. Éric

    Avoir un unique fichier à télécharger côté navigateur, avoir un unique fichier côté développement, et ne pas dupliquer des règles CSS sont trois problématiques différentes.

    Quand la CSS globale devient trop importante tu peux exploser ta CSS en plein de petits fichiers côté développement et chaque type de page va chercher un fichier CSS qui sera en fait juste l’aggrégation des différents petits fichiers utiles. Pas besoin de dupliquer le code côté développement.

    Après effectivement, avoir une CSS différente par type de page met en échec partiel le cache sur les feuilles de style. Il faudra retélécharger la CSS à chaque fois que tu passes sur un nouveau type de page. C’est à toi de faire les calculs pour voir ce qui est intéressant suivant la taille de ta CSS globale, ce que tu peux gagner en différenciant les CSS sur chaque type de page, le nombre de pages visitées en moyenne par tes visiteurs, la proportion de nouveaux visiteurs.

    J’avais fait un de mes premiers billets sur cette problématique http://performance.survol.fr/2008/03/strategies-doptimisation-du-cache/
    Yahoo a aussi publié quelques stats sur l’utilisation du cache qui peuvent modérer le côté négatif d’avoir des CSS différentes http://yuiblog.com/blog/2007/01/04/performance-research-part-2/

    Concernant les reflow, je ne vois pas pourquoi ça serait le cas mais je n’en sais rien, à tester.

    Par contre tu devrais de toutes façons concaténer ta reset.css et ta CSS principale. Vu le faible poids de la reset, la séparer n’a aucun bénéfice ou presque

  8. Florent V.

    Le graphique n’est pas très parlant. Si on prend les résultats pour MSN.com, Facebook et MySpace, on obtient trois profils très différents desquels on peut tirer des conclusions inverses («le temps de reflow est directement corrélé à la complexité des sélecteurs» et «la complexité des sélecteurs a une influence nulle ou faible sur le temps de reflow»). Sans parler des probables différences entre les navigateurs, qui n’ont sans doute pas fait les mêmes choix techniques. Rien de probant sur la complexité des sélecteurs, donc.

    La corrélation entre nombre de règles CSS et le temps de reflow me semble plus claire. J’aurais aussi apprécié de voir une courbe du nombre de déclarations CSS, et pourquoi pas du nombre de nœuds DOM, et du nombre total de déclarations appliqués aux différents nœuds (moyennant quelques multiplications savantes). Les deux critères retenus dans ce graphique ne me semblent pas être les plus intéressants, même s’ils sont plus simples à obtenir. :/

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>