Sélecteur CSS de frère adjacent (Dirty Grids Done Dirt Cheap)

L’ajout des classes CSS pour spécifier la largeur des colonnes dans le code HTML est le lot des frameworks CSS qui proposent tous un mécanisme pour créer une grille de mise en page. Dans leur très grande majorité, ces frameworks ont besoin d’une classe pour la première colonne (.first pour The Simpler Grid) ou la dernière colonne (.last pour Blueprint CSS) voire pour la première et la dernière colonne (.alpha et .omega pour 960 Grid System) pour annuler les marges droites et/ou gauches attribuées par avance aux colonnes.

Dans ma liste de plus de 30 frameworks CSS, seul inuit.css s’affranchit de ces classes .first, .last, .alpha ou .omega. Mais c’est au prix d’un décalage global du container (.grids, en l’occurrence) de la valeur de la gouttière. Je suis assez admiratif de cette technique et je m’en veux de ne pas l’avoir trouvée au lieu de faire l’intéressant avec mon mashup de Blueprint CSS, The Simpler Grid, 960.gs !

Sélecteur de frère adjacent

Dans mes mises en page web, j’utilise souvent un nombre de colonne différent selon le contexte :

  • contenu principal avec deux ou trois colonnes en page d’accueil ;
  • contenu principal avec une colonne lorsque j’affiche le contenu d’un article seul.

C’est là qu’intervient le sélecteur de frère adjacent, symbolisé par le signe «+».

La spécification des CSS 2 nous apprend que :

Les sélecteurs d’enfants adjacents suivent une syntaxe de cette forme : E1 + E2, où E2 est le sujet du sélecteur. Celui-ci est vérifié quand E1 et E2 ont le même parent dans l’arbre du document et quand E1 y précède immédiatement E2.

J’avais l’habitude de me servir de ce sélecteur pour supprimer l’alinéa du premier paragraphe qui n’a littéralement aucune raison d’être ici, puisque par définition, il n’y a rien à mettre «à la ligne» :

p + p {
    text-indent: 1em;
}

Ici, étant donné que le deuxième p est le sujet du sélecteur, on sous-entend que le premier n’est pas indenté.

.sidebars + .sidebars = grille ?

Je me suis dit qu’il pourrait être intéressant d’utiliser cette propriété dans le cas où le nombre de colonnes varie, sans être obligé de définir le contexte de manière trop précise. L’exemple qui suit illustre à merveille ce concept 🙂

#sidebar { margin-left: 20px; }
#sidebar .sidebars + .sidebars {
    margin-left: 20px;
}

#sidebar contient entre une et deux colonnes. Lorsqu’une seule .sidebars est présente, je n’ai pas besoin de spécifier de marge gauche (1) (celle de #sidebar suffit à créer la gouttière entre #main (le contenu de l’article) et #sidebar). Lorsqu’il y a deux .sidebars dans #sidebar, seule la deuxième doit avoir cette marge gauche pour créer la gouttière. Et voilà !

(1) j’utilise une marge gauche pour créer des gouttières afin de pouvoir annuler la marge du premier élément — au cas où j’aurais appliqué un float: left et un margin-left: 20px à toutes mes colonnes — avec le pseudo-sélecteur :first-child (CSS 1) pris en charge plus largement que :last-child qui nous arrive tout juste avec CSS3.

Dans le cas d’une troisième .sidebars, il suffirait donc d’utiliser une déclaration du type :

#sidebar .sidebars + .sidebars + .sidebars {
    margin-left: 20px;
}

On s’en «grille» une ?

Voici un exemple d’une rangée de 12 colonnes bâtie sur ce principe avec une version en ligne de cette  grille CSS (notez l’utilisation des rôles WAI-ARIA en action) :


#page { 
  width: 940px; 
  margin: 0 auto; 
  text-align: center; 
} 
[role="banner"], 
[role="contentinfo"] { 
  clear: both; 
  background: #333; 
  color: #eee; 
} 
[role="main"] > div { 
  width: 60px; 
  float: left; 
  background: #eee; 
  margin: 1.539em 0; 
} 
[role="main"] > div + div { 
  margin-left: 20px; 
}

Un système encore expérimental

Cette utilisation du sélecteur d’enfant adjacent est encore expérimentale et devrait faire l’objet de tests plus approfondis pour voir où elle peut nous mener. En tout état de cause, cette technique ne nécessite à priori aucune intrusion intempestive dans le code HTML si votre page est bien structurée (ce qui est sûrement le cas). Je compte sur vous pour tester ce concept qui en a sous la botte — ou le talon aiguille — afin d’en tirer la substantifique moelle 🙂