En fait je ne suis pas d'accord sur un point avec Google, mais j'ai peut être tord... C'est pourquoi j'aimerais avoir vos avis sur la question Smiley cligne

L'objectif de Google Page Speed est de nous informer sur les points que l'on pourrait améliorer pour décroitre le temps d'affichage de nos pages aux internautes.

Sauf que, pour le point "Use efficient CSS selectors", Google nous recommande de ne pas utiliser les éléments parents dans la hiérarchie pour désigner un élément enfant.

a écrit :
"Avoid using descendant selectors, especially those that specify redundant ancestors. Use class selectors instead of descendant selectors"


Avec l'exemple suivant :


/* Pas bien */
ul li {color: blue;}
ol li {color: red;}

/* Bien */
.unordered-list-item {color: blue;}
.ordered-list-item {color: red;}


Utiliser l'arbre des éléments pour désigner l'élément enfant ralentirait apparemment le travail des navigateurs, qui doivent évaluer l'ensemble des éléments en partant de la droite, puis faire le tri dans ce qu'ils gardent et ce qu'ils jettent.

Mais cela justifie t-il un alourdissement des pages HTML et des feuilles de style ?

Parce que si je comprend bien, je devrais effectuer les modifications suivantes :


/* Avant */
.article h2 a {color:#000}

/* Après */
.article-title-link {color:#000}



<!-- Avant -->
<div class="article">
<h2><a>Mon titre</a></h2>
</div>

<!-- Après -->
<div class="article">
<h2><a class="article-title-link">Mon titre</a></h2>
</div>


J'accélère le temps d'analyse de la page par le navigateur mais j'alourdis le poids des pages...
Modifié par Raphael (18 Mar 2010 - 07:38)
Hello magentix et bienvenue,

qu'il s'agisse des recommandations de Google ou de celles de Mozilla il ne s'agit que de recommandations se basant sur un point très spécifique qui est celui d'optimiser les sélecteurs CSS. Il faut bien sûr tenir compte de tous les autres facteurs (poids des fichiers, lisibilité du code, maintenance, priorité, etc.) et choisir ensuite son propre compromis.

Personnellement ce point est vraiment le moins important de tous et je me contente <edit> ou pas Smiley lol </edit> de simplifier au maximum (si cela n'a pas d'incidence). Par exemple :
#menu img
au lieu de
ul#menu li a img

Modifié par Heyoan (17 Mar 2010 - 14:17)
Merci pour la réponse Smiley cligne

C'est vrai qu'à force de suivre à la lettre les recommandations j'en oublie parfois mon jugement personnel Smiley langue . J'ai même appliqué le "Serve static content from a cookieless domain" en créant un sous domaine pour éviter de se trimbaler les cookies dans les en-têtes...

Mais bon l'optimisation exagérée c'est finalement assez formateur (et amusant).
Administrateur
Bonjour,

+1 avec Heyoan, ça vient en dernier dans mes priorités et en général c'est plus les contraintes du client qui me dictent qu'est-ce que j'écris à gauche de chaque sélecteur de règles CSS que les performances du moteur de rendu. Est-ce que le client va décliner les gabarits intégrés (réutilisation) ou au contraire est-ce que ça ne doit à tout prix pas impacter un autre gabarit ou une autre partie de la page (isolation) ?
Par contre les sélecteurs jQuery là oui je ferais attention.
Tout comme Heyoan.

Pour moi cette recommandation représente:
- un bilan faible ou nul pour les performances client (gain pas énorme sur l'exécution du CSS, perte sur le poids des pages HTML);
- un impact négatif sur le temps d'intégration et de maintenance (code HTML plus difficile à écrire, code CSS moins lisible).

Si un expert du sujet (hint, hint) passe par là, je veux bien avoir son avis. Smiley smile
Bon, déjà attention aux recommandations de performance, ce sont des recommandations, pas des règles. Bref, il faut appliquer votre discernement par dessus.

Concernant les sélecteurs CSS c'est une reco qui a assez peu d'impact sur des petits sites, ou des petites CSS. Bref, attention à ne pas en faire quelque chose de majeur.

Maintenant le rendu est effectivement impacté par les sélecteurs CSS et le temps de traitement CSS n'est pas négligeable sur les sites qui ont quelques dizaines de milliers de noeuds DOM avec 50k de CSS. L'exemple donné est probablement celui qu'il ne faut pas mettre en application, mais il est parfait ... comme exemple, pour comprendre la préco.

L'idée c'est qu'un sélecteur CSS s'interprête de droite à gauche. En gros sur "A B C" on commence par sélectionner toutes les balises qui correspondent à C, puis pour chacune on remonte la hiérarchie pour voir si elle contiennent un B, puis un A. S'il y a beaucoup de noeuds qui correspondent à C, ou si la correspondance à C nécessite de vérifier tous les noeuds du document, ou si les noeuds trouvés sont très profonds dans l'arbre, cela prend du temps.

- Sont à bannir ou à éviter autant qu'on peut quels que soient les sites les sélecteurs qui se terminent par * doivent être bannis (si on peut) ou qui ne se terminent pas par un nom de classe, un nom de balise, ou un identifiant (ce qui revient à un * implicite). Cela demande de scanner tous les noeuds DOM de la page et c'est forcément lourd (la CSS n'est pas appliquée une seule fois au démarrage, mais très souvent au gré des interactions avec la page).

- Sont à éviter fortement les sélecteurs qui se terminent par un nom de balise extrêmement fréquent (par exemple div et span sur les sites montés "à la mode") parce que finalement ça revient à scanner quand même un très grand nombre de noeuds

- Sont à très fortement privilégier les noms de classe et les identifiants dans les parties la plus à droite du sélecteur (on utilise un index qui permet des correspondances très rapides)

- Surspécifier un sélecteur est négatif. Si votre noeud avec la classe .toto est dans un div #tata, faire "#tata .toto" n'aide *pas* le navigateur contrairement à ce que certains pensent, ça le ralentit. Il vaut mieux faire un simple ".toto"

Découle de tout ce qui précède, que faire un "#toto li div" est assez lent. Il vaut mieux mettre une classe au div et spécifier cette classe (quitte à mettre le #toto à gauche). C'est l'exemple donné.

Ca n'impacte pas beaucoup les petits sites et les petites css (sauf pour la première préco et éventuellement la seconde) et ce n'est généralement pas nécessaire de réécrire les règles qui ne correspondent pas aux deux premières précos, maintenant ça peut être bon à garder en tête pendant la construction.

Après tout est histoire de mesure, on ne va pas non plus mettre des classes à rallonge de partout mais on évite aussi de scanner 600 fois tous les noeuds pour rien. A vous de trouver la mesure.


Voilà voilà, ça répond aux questions ?
Merci beaucoup pour la réponse Edas, très intéressant.

Je pense revoir un peu ma manière d'écrire mes CSS (en lignes), car ce n'est que depuis peu que j'intéresse de très près aux gains de performances (bien que ridiculement minimes dans certains cas, il est nécessaire de toujours les avoir en tête lors du développement du site).

Car un site s'enrichit et s'alourdit avec le temps, un site dont tous les éléments d'optimisation ont été étudiés dès le départ sera plus à même de maintenir de bonnes performances dans la durée.

Je privilégiais jusqu'à maintenant (jusqu'à la lecture des recos) la compréhension générale de mes CSS, avec une redondance des sélecteurs pour faciliter la clarté de mon arbre :


.articles h2 a { ... }
.articles h2 a span {...}
.articles .article p { ... }
.articles .article p span { ... }


Dans cet exemple, si cela est possible et comme Heyoan le suggérait, on pourrait se contenter de :


.articles h2 a { ... }
.articles h2 span {...}
.article p { ... }
.article span { ... }


Bref, mon choix sera de garder ma façon habituel de coder pour gagner du temps lors des maintenances et du développement, puis de "nettoyer" l'intégralité du CSS en retirant les éléments superflus avant mise en ligne, afin de gagner en performance sur les temps de chargement (avec sous les yeux mon balisage "nu").
Arf désolé pour la petite erreur, Magentix et FloatLeft sont la même personne Smiley cligne (J'avais oublié mes précédents identifiants sur ma machine au bureau)
floatLeft a écrit :
Bref, mon choix sera de garder ma façon habituel de coder pour gagner du temps lors des maintenances et du développement, puis de "nettoyer" l'intégralité du CSS en retirant les éléments superflus avant mise en ligne, afin de gagner en performance sur les temps de chargement (avec sous les yeux mon balisage "nu").

J'ai pris l'habitude d'écrire des sélecteurs aussi réduits que possibles (sans rajouter des classes ou identifiants «inutiles» dans le code HTML pour cela). Donc je n'écris jamais .articles .article p, et toujours .article p. Je n'ai pas remarqué de difficulté particulière pour relire mon code à cause de ça. Mais bien sûr c'est mon code donc ça aide, et je le structure logiquement et le commente pour organiser les styles ou annoter certains blocs afin d'éviter les ambiguïtés.

Je pense que si tu ne prends pas l'habitude de coder directement de manière «brève», revenir sur ton code pour abréger tous les sélecteurs te fait courir le risque de casser des choses (portée du nouveau sélecteur trop importante, priorités des sélecteurs changées...). J'éviterais ça.
Je confirme, côté performance il y a bien des choses à faire avant de réécrire la CSS avec les risques que ça comporte et la possibilité que l'influence soit négligeable voire invisible.
Sauf si vous avez une très grosse CSS (on compte > à 50ko) sur un site complexe avec des sélecteurs tout pourris (partie à droite sans classe ou identifiant), travaillez autre chose.
Franchement, à part sur Amazon et cie, ce genre d'optimisation apporte vraiment quelque chose ?

Ca revient à quoi ?
10 millièmes de seconde de gagnés ?
A ce niveau c'est quasiment impossible d'évaluer. Mais bon, je suis du genre à passer pas mal de temps sur ce type de questions, d'une part parce que je suis atteint d'un "perfectionnisme chronique" (uniquement pour ce qui touche au dev en fait), d'autre part parce que je gère un e-commerce important où les CSS pèsent en effet plus de 50ko (et où le choix sémantique et la construction hiérarchique des éléments devient rapidement un vrai casse tête).
Administrateur
Edas a écrit :
avec des sélecteurs tout pourris (partie à droite sans classe ou identifiant)

En clair, mieux vaut une classe / id qu'un sélecteur d'élément bien ciblé ? Smiley ohwell


C'est quand-même un peu rageant de se dire qu'on a de nouveaux sélécteurs tout beaux depuis CSS2.1 (adjacent, enfant, attribut, ...) et qu'il faudrait y préférer une classite / divite.

En gros, ce genre de tests de performances nous inciteraient à fourrer des classes partout plutôt que d'utiliser des sélecteurs pourtants faits pour ça :
- utiliser #nav > ul est plus lent que .mon-ul-de-nav
- utiliser h1 + p est plus lent que d'attribuer une classe à 50 paragraphes
- etc.

Heureusement que c'est négligeable, parce que j'ai moyennement envie de retourner dans les années 90' Smiley sweatdrop
Modifié par Raphael (18 Mar 2010 - 07:36)
Raphael a écrit :
En clair, mieux vaut une classe / id qu'un sélecteur d'élément bien ciblé ? Smiley ohwell

Ça dépend. Si j'ai bien compris, un sélecteur comme #mon-module .ma-classe sera aussi performant (ou pas loin) d'un .ma-classe tout court, tout en étant bien ciblé. Par contre un #mon-module li sera moins performant car le navigateur doit parcourir tous les LI du document et vérifier pour chaque qu'il a bien pour ancêtre un élément qui a l'identifiant "mon-module".

Mais on ne peut pas affirmer que #mon-module li est un mauvais sélecteur ou un moins bon sélecteur dans l'absolu, car il n'y a pas que le critère des performances client qui rentre en ligne de compte, comme déjà rappelé dans ce sujet. Smiley cligne
Modifié par Florent V. (18 Mar 2010 - 09:46)
@Skoua: On gagnera la même chose sur Amazon que sur n'importe quel site. Ou dit autrement on gagnera autant sur vos sites que sur Amazon. On parle là d'optimisations sur le navigateur, qui n'impactent que le client. Du coup qu'on parle du site le plus visité au monde ou d'un site perso, ça ne change strictement rien. Seuls la taille et la complexité de la CSS ou de la page HTML influent.


Savoir si c'est 10ms, je serai incapable de te dire, d'autant que ça dépend trop des sites et de ce que vous en faites. Des fois ça a une influence réelle et non négligeable, des fois tu seras bien à mal de le mesurer tout court. Dans tous les cas le savoir ne fait pas de mal.

Dans tous les cas travailler sur le poids des images, sur les caches HTTP, sur la compression ou la minimisation des contenus, sur l'organisation des javascript, a de bonnes chances d'amener des meilleurs gains si vous n'avez pas déjà travaillé ces points là.

Maintenant un peu d'humilité : si les experts (je ne parle pas de moi, mais des gens autour de Page Speed par exemple) affirment que ça peut avoir une influence réelle, as tu des éléments sérieux pour le mettre en doute à part une intuition qui n'est pas toujours bonne conseillère ?
Quitte à citer, je préfère citer les synthèses que les essais temporaires : http://www.stevesouders.com/blog/2009/06/18/simplifying-css-selectors/

Son premier test est assez biaisé dans le sens où sa mise en page assez simple ne demande à la CSS que de s'appliquer une fois au démarrage. Dans les mises en page modernes il est fréquent que la CSS doivent se réappliquer et le rendu se recalculer, et ça peut impacter plus que prévu avec des sélecteurs pourris.

Le site sur lequel je travaillais l'année dernière avait 25ko de CSS après passage par gzip, plus de 100ko avant, et des travaux javascript qui impactent le rendu un peu partout. Bref, ça avait de l'influence alors.

Ca a quand même assez eu d'influence pour qu'il en fasse un chapitre dans son livre, que Google (où il est embauché justement pour travailler sur les perf) ajoute cette notion à Page Speed.

Il faut juste de la mesure et savoir quand est-ce que ça vaut le coup et pourquoi. Remplacer un "ul.toto li" n'a pas beaucoup de raison d'être. Eviter de placer un "#toto div *" sur un site pas mal complexe a plus de raison d'être une fois qu'on a identifié que le rendu était un problème de perf.