Écriture de CSS efficace

Ce document vous donne des indications pour optimiser votre code CSS, et plus particulièrement comment écrire des sélecteurs efficaces.

La spécification CSS ne précise pas comment les navigateurs doivent implémenter le système de style, mais le résultat final. De fait, de nombreux moteurs de styles peuvent avoir des comportements très différents en terme de performance. Gecko et WebKit, tous deux libres, utilisent des algorithmes similaires, avec des forces et des faiblesses similaires. Les astuces présentées ici seront donc utiles pour les documents réels du Web.

La première section traite de la manière habituelle dont les styles sont catégorisés. Basé sur cette connaissance, les sections suivantes contiennent des indications qui utilisent ce style de système d'implémentation.

Comment le système de style différencie les règles

Les règles de style sont tout d'abord séparées en quatre catégories

  1. Règles d'identifiant
  2. Règles de classe
  3. Règles de balise
  4. Règles universelles

Il vous est nécessaire de comprendre ces catégories, car elles sont les blocs fondamentaux utilisés pour construire les règles d'attribution des blocks.

La clé de sélection, dans les paragraphes suivants, signifie l'extrémité du sélecteur (celle qui pointe vers l'élément souhaité, et non un de ses ancêtres).

Par exemple, dans la règle

a img, div > p, h1 + [title] {…} 

les clés de sélections img, p, et [title].

Règles d'identifiant

La première catégorie de règles concerne les règles qui utilisent un champ ID comme clé de sélection.

Exemple
button#backButton {…} /* This is an ID-categorized rule */
#urlBar[type="autocomplete"] {…} /* This is an ID-categorized rule */
treeitem > treerow > treecell#myCell:active {…} /* This is an ID-categorized rule */ 

Règles de classe

Concerne les règles qui utilisent l'attribut class comme clé de sélection.

Exemple
button.toolbarButton {…} /* A class-based rule */
.fancyText {…}	/* A class-based rule */
menuitem > .menu-left[checked="true"] {…} /* A class-based rule */ 

Règles de balise

S'il la clé de sélection n'est ni class, ni ID, le système considère alors les balises. Si une règle utilise une balise comme clé de sélection, alors c'est ce type de règle qui est utilisé.

Exemple
td {…} /* A tag-based rule */
treeitem > treerow {…} /* A tag-based rule */
input[type="checkbox"] {…} /* A tag-based rule */ 

Règles universelles

Toutes les règles qui sont hors des catégories précédentes

Exemple
[hidden="true"] {…} /* A universal rule */  
* {…}		/* A universal rule */
tree > [collapsed="true"] {…} /* A universal rule */

Comment le système de style attribue les règles

Le système de style attribue les règles en commençant par la clé de sélection, puis en allant à gauche (c'est-à-dire vers les ancêtres du sélecteur de règle). Tant que possible, le système de style continue de chercher à gauche une attribution possible, jusqu'à ce qu'il en trouve une ou s'arrête sans rien.

Le concept le plus important ici est le filtrage des règles. L'utilisation de catégories permet de filtrer les règles non applicables, ce qui évite au système de perdre du temps à essayer de les attribuer.

C'est le moyen d'améliorer de façon notable les performances. Le moins d'essais d'application de règles , le plus vite la résolution de style.

Par exemple, dans le cas d'un élément avec un identifiant (ID), seules les règles liées à l'identifiant vont être lues. Si un élément possède de plus un attribut de classe, alors seules les règles de sa classes vont être lues, et enfin seules les règles correspondant à sa balise vont être lues. Les règles universelles seront elles toujours lues.

Guide pour écrire un CSS efficace

Éviter les règles universelles

Faites votre possible pour éviter qu'une règle ne se trouve dans la catégorie universelle!

N'utilisez pas de classe ou de balise en plus d'un identifiant

Si une règle est basée sur un sélecteur d'identifiant, n'utilisez pas une balise ou une classe en plus: les identifiants sont uniques, et l'utilisation des balise va ralentir l'attribution sans bénéfice aucun.

Exception: Il peut être souhaitable de changer dynamiquement la propriété class d'un élément pour varier le style en fonction de la situation, quand d'autres éléments utilisent la même classe.
Éviter
button#backButton {…}
Éviter
.menu-left#newMenuIcon {…}
Préférer
#backButton {…}
Préférer
#newMenuIcon {…}

N'utilisez pas une balise en plus d'une classe

Dans la même logique que précedemment, utiliser une balise en plus d'une classe est contre-productif.

Vous pouvez, si vous le souhaitez, inclure le nom d'une balise dans le nom de classe. Cependant, ceci se fera au détriment de la flexibilité : si des changements sont apportés à la mise en page, tous les noms de classe doivent aussi être changés. Nous vous conseillons d'utiliser plutôt des désignations adaptés au sens de votre page, car une feuille de style devrait rester flexible.

Éviter
treecell.indented {…}
Plutôt
.treecell-indented {…}
Préférer
.hierarchy-deep {…}

Utiliser la catégorie de règles la plus précise possible

La principale cause de ralentissement est l'abondance de règles dans la catégorie des balises. Vous pouvez, en ajoutant un attribut de classe à vos éléments, les diviser en classes, et ainsi éliminer le temps perdu à essayer d'attribuer des règles à une balise.

Éviter
treeitem[mailfolder="true"] > treerow > treecell {…}
Préférer
.treecell-mailfolder {…}

Se méfier du sélecteur descendant

Le sélecteur descendant est le sélecteur le plus gourmand du CSS. Il est incroyablement lourd, en particulier si le sélecteur est dans la catégorie des balises ou la catégorie universelle.

Vous aurez besoin, le plus souvent, du sélecteur fils. S'il vous faut un autre argument pour vous convaincre, sachez que le sélecteur descendant est tout simplement interdit dans les fichiers CSS de l'interface utilisateur de Firefox, et ce sans aucune justification. Vous devriez en faire de même dans vos pages internet.

Éviter
treehead treerow treecell {…}
Mieux, mais toujours non optimal (lisez la suite)
treehead > treerow > treecell {…}

Les règles de balise ne devraient jamais avoir de sélecteur fils

Évitez d'utiliser le sélecteur fils avec des règles de catégories. Ceci ralentira par trop le traitement par la machine à chaque élément listé. Cet effet est d'autant plus fort qu'il est probable que la règle soit appliquée.

Éviter
treehead > treerow > treecell {…}
Préférer
.treecell-header {…}

Posez-vous la question de l'utilisation du sélecteur fils

Utilisez le sélecteur fils avec précaution, et, si possible, ne l'utilisez pas.

Le sélecteur fils est trop souvent utilisé lors du parcours des arbres RDF et des menus, comme par exemple:

Éviter
treeitem[IsImapServer="true"] > treerow > .tree-folderpane-icon {…}

Sachez que les attributs REF peuvent être copiés dans un modèle de document! Profitez-en, par exemple en copiant les propriétés RDF des éléments fils d'un élément XUL, et en les sélectionnant sur leurs attributs.

Préférer
.tree-folderpane-icon[IsImapServer="true"] {…}

Utiliser l'héritage

Sachez quelles sont les propriétés transmises par héritage, et abusez-en!

Par exemple, les gadgets XUL sont configurés pour que les règles list-style-image ou font filtrent jusqu'à un contenu anonyme. Ne perdez donc pas de temps sur des règles qui portent sur le contenu anonyme.

Éviter
#bookmarkMenuItem > .menu-left { list-style-image: url(blah) }
Préférer
#bookmarkMenuItem { list-style-image: url(blah) }

Dans l'exemple ci-dessus, la recherche de l'élément anonyme (sans prendre en compte l'héritage de list-style-image) a fait passer la règle dans la catégorie classe, alors qu'elle devrait être dans la catégorie d'identifiants, c'est-à-dire la catégorie la plus restreinte!

Pense-bête: tous les éléments ont la même classe, et en particulier les éléments anonymes!

La « mauvaise règle » ci-dessus va vérifier pour chaque élément que celui-ci est bien un élément du menu des marques-pages. C'est très coûteux, car il existe de nombreux menus. A contrario, la « bonne règle » limite la recherche aux éléments du menu des marques-pages.

Utilisez la propriété -moz-image-region!

Groupez plusieurs images dans une grande image et sélectionnez-en une partie avec -moz-image-region. Ceci fonctionne beaucoup plus vite que si chaque image est dans son propre fichier.

Délimiter la portée des feuilles de style

Si vous ajoutez une feuille de style comme ressource XBL, les styles sont liés uniquement à leurs éléments et leur contenu anonyme. Ceci limite la perte d'efficacité liées aux règles universelles et aux sélecteurs fils, car le nombre d'élément à considérer est moindre.

Étiquettes et contributeurs liés au document

Contributeurs ayant participé à cette page : rd6137, PhenX
Dernière mise à jour par : rd6137,