Le sélecteur d’adjacence indirecte est peu connu en CSS.
Arrivé avec la nouvelle mouture CSS3, ce sélecteur vous permet de sélectionner d’un seul coup tous les frères d’un élément ciblé répondant à un sélecteur précis.
Voyons voir avec quelques exemples comment l’utiliser et quels sont ses effets.

Syntaxe de base

Le sélecteur, que j’appelle incorrectement siblings du fait de sa ressemblance avec la fonction siblings() de jQuery, utilise le caractère ~ disponible sous PC depuis les touches Alt Gr + 2(é ~).

element1 ~ element2 {
/* mes styles */
}

Ici les styles seront appliqués à tous les element2 frères de element1, même si un autre frère vient se mêler entre deux element2, par exemple.

Voir la démo

Il est important de noter que ce sélecteur ne cible que les frères suivants d’un élément. En aucun cas les frères précédents ne seront concernés.

Quelques exemples d’utilisations

En réalité je n’en ai pas trouvé tant que ça, peut-être par habitude d’utiliser d’autres techniques.
Généralement la technique li + li pour cibler tous les frères du premier li dans une liste, par exemple, me suffit.

Cibler les frères non identiques à l’élément de départ

Cependant ce sélecteur d’adjacence indirecte (~) va permettre de combler certaines lacunes du sélecteur d’adjacence directe (+).
Il sera capable de cibler tous les paragraphes qui suivent un titre, par exemple. Chose qui ne fonctionnera pas en faisant h3 + p, mais qui fonctionnera avec h3 ~ p.

Cibler les frères d’un élément survolé, ciblé ou typé

Dans la même logique que précédemment, il est possible de cibler, par exemple, tous les frères d’un li survolé (donc les autres li), ou d’un input typé.

li:hover ~ li {
opacity: 0.4;
}

Cet exemple provient d’un effet produit sur jq.creativejuiz.fr (avec une solution jQuery), ou sur la récente démonstration de Raphaël Goetter sur un fil d’ariane entièrement conçu en CSS : Breadcrumbs without images.

Ou avec le deuxième exemple :

input[type="radio"] ~ input {
   margin-left: 2.6em;
}

Ce qui permettrait, dans un enchaînement de input + label de type radio, d’espacer les choix.
Démonstration

Exemple de factorisation pour les niveaux de titre

J’ai essayé d’aller plus loin encore, avec des choses un peu poussées… un peu trop peut-être.
Je m’explique.

Je ne sais pas si la pratique est courante, mais il peut-être intéressant d’avoir une indentation des blocs de texte en fonction du niveau dans lequel on se trouve dans un document (pas du niveau dans le DOM, mais dans la hiérarchie des titres).
C’est surtout dans un contexte de forte densité de texte que je vois l’intérêt.
Voici une illustration de mon propos : voir la démonstration.

Comme vous pouvez le voir, une marge à gauche est appliquée en fonction du niveau de titre qui précède le contenu.
Ou plutôt, en terme de CSS, tout ce qui suit un niveau de titre se verra appliquer une marge en conséquence.
La marge n’est qu’un exemple parmi d’autres, on peut très bien imager d’autres styles plus colorés.

Vous avez le droit de vous dire que sur le web ça ne sert pas à grand chose et qu’on cherche souvent à avoir un contenu épuré… soit, mais imaginons.

Avant de vous donner du code, je tiens à préciser que ça ne fonctionne pas. En effet, dans le cas présent, je place les uns à la suite des autres des titres, paragraphes et listes.
Il n’y a donc aucune profondeur, aucun sectionnement du contenu.

Voici la CSS (version pour Firefox) de l’exemple, si vous ne l’avez pas déjà analysée directement dans la démo :

.ex2 h3 {
	margin-left: 1em;
}
.ex2 h3 ~ :-moz-any(p, ul, blockquote, h4) {
	margin-left: 2em;
}
			
.ex2 h4 {
	margin-left: 4em;
}
.ex2 h4 ~ :-moz-any(p, ul, blockquote, h5) {
	margin-left: 5em;
}
			
.ex2 h5 {
	margin-left: 7em;
}
.ex2 h5 ~ :-moz-any(p, ul, blockquote, h6) {
	margin-left: 8em;
}
			
/* 
	permettre de remonter dans la hiérarchie...
	mais pas trop...
*/
.ex2 h5 ~ h4 ~ :-moz-any(p, ul, blockquote, h5) {
	margin-left: 5em;
}
			
.ex2 h4 ~ h3 ~ :-moz-any(p, ul, blockquote, h4) {
	margin-left: 3em;
}

Vous remarquerez l’utilisation de any(), pseudo-classe vue précédemment dans l’article « CSS3 – Any(), pseudo-classe prometteuse et économe« , qui me permet d’économiser quelques lignes de code.

Voyez-vous où le problème se pose ?
En fait, un paragraphe (ou liste) qui se trouve après un h3 qui serait lui même après un h4 se verrait appliquer les styles d’un paragraphe (ou liste) se trouvant après un h4. Et oui ! Puisque dans l’absolu, ce p, même si précédé d’un h3, se trouve frère d’un h4.

Euh… ça va ? Je ne vous ai pas perdu ?

Sinon pour information, ce sélecteur est compatible avec IE7 et version supérieure, génial non ?

C’était une simple réflexion sur l’utilisation de ce sélecteur.
Et vous, vous en pensez quoi ?
Je vous laisse me dire comment vous voyez l’utilisation de ce sélecteur.

Je rends l’antenne.
À vous !