Sélecteurs CSS avancés

Alexandre Niveau
GREYC — Université de Caen
En partie adapté du cours de Jean-Marc Lecarpentier

Sélecteurs CSS simples

  • On sait sélectionner un élément
    • en fonction de son type
    • en fonction de sa classe
    • en fonction de son identifiant
  • On sait aussi combiner des sélecteurs, pour sélectionner les éléments qui descendent d'un autre élément
  • Avec ça, on peut déjà faire énormément de choses
  • Cependant, pour faire des choses précises, on a souvent besoin d'ajouter des blocs (typiquement des div), ce qui n'est pas très propre (le HTML doit rester sémantique)
  • Mais surtout on a besoin d'utiliser beaucoup de classes, ce qui peut devenir difficile à maintenir

Mieux profiter des CSS

  • CSS comprend aussi des sélecteurs plus avancés, qui permettent de limiter les divisions inutiles et le nombre de classes en s'appuyant au maximum sur les informations données « naturellement » par le HTML :
    • sélecteurs de descendance
    • sélecteurs d'adjacence
    • pseudo-classes
    • pseudo-éléments
  • On peut également associer tous ces sélecteurs ensemble, et notamment avec les classes.

Sélecteurs de descendance

  • Descendance
    nav a : tout élément a descendant d'un élément nav
  • Enfant
    nav > a : tout élément a fils direct d'un élément nav
<nav>
	Liste de liens :
	<ul>
		<li><a href="#">un lien dans la liste</a></li>
		<li><a href="#">un autre lien dans la liste</a></li>
	</ul>
	On peut aussi cliquer sur <a href="#">ce lien-ci</a>
	ou <a href="#">celui-là</a>, mais ils ne sont pas dans la liste.
</nav>
nav a {
	color: tomato;
}

nav > a {
	font-weight: bold;
}

Sélecteurs d'adjacence

  • Adjacence +
    h2 + p : tout élément p suivant immédiatement un élément h2
  • Parent commun ~
    h2 ~ p : tout élément p suivant un élément h2 (mais pas forcément immédiatement)
  • NB : comme pour les sélecteurs de descendance, l'élément sur lequel s'applique la règle est le dernier
<ul>
	<li>un item</li>
	<li class="toto">un item de classe <code>toto</code></li>
	<li>un autre item</li>
	<li>un autre item</li>
	<li>un dernier item</li>
</ul>
<p>Une deuxième liste :</p>
<ul>
	<li>avec un item</li>
	<li>et un autre</li>
</ul>
.toto + li {
	color: forestgreen;
	font-weight: bold;
}

.toto ~ li {
	background-color: gold;
}
  • un item
  • un item de classe toto
  • un autre item
  • un autre item
  • un dernier item

Une deuxième liste :

  • avec un item
  • et un autre

Attention, dans les deux cas, les deux éléments doivent avoir le même parent ! Dans l'exemple, les li de la deuxième liste ne sont pas colorés.

cf démo 16/17. intégrer dans cours ?

Pseudo-classes

  • Autre catégorie de sélecteurs plus avancés
  • Objectif : pouvoir sélectionner des éléments ayant une caractéristique qui peut changer dynamiquement
  • Par exemple, pour changer la couleur des liens lorsque l'on passe la souris dessus :
    a:hover { color: black; background-color: red; }
    
  • :hover est une pseudo-classe : c'est comme si le navigateur ajoutait en direct une classe spéciale à un lien qui est en train d'être survolé
  • Syntaxe : utilise un deux-points au lieu d'un point
  • Attention, on peut utiliser n'importe quoi comme nom de classe, mais la liste des pseudo-classes utilisables est fixée ! Chaque pseudo-classe a un sens précis connu par le navigateur.

Styler les liens

  • Pseudo-classes concernant les liens :
    a:link { color: green; }  /* par défaut */
    a:visited { color: orange; }  /* déjà visité */
    a:hover { color: black; background-color: red; }  /* lors du survol */
    a:focus { color: #aaa; text-decoration: line-through; }  /* focus clavier */
    a:active { color: yellow; }  /* lors du clic */
    
  • Résultat : exemples de liens qui utilisent CSS
  • Attention à l'ordre !

Utilisation de ces pseudo-classes sur d'autres éléments

  • On peut modifier le style de n'importe quel élément en fonction de la position de la souris, ou de la convergence clavier quand cela a un sens :
    <p>Passer la souris sur cette phrase</p>
    <input type="text" value="Mettre le curseur ici" />
    <p>Cliquer sur le mot en gras : <strong>dimétrodon</strong></p>
    p:hover {
    	background-color: aquamarine;
    }
    
    input:focus {
    	background-color: tomato;
    }
    
    strong:active {
    	background-color: gold;
    }
    

    Passer la souris sur cette phrase

    Cliquer sur le mot en gras : dimétrodon

  • :hover est extrêmement utile pour rendre les pages un peu plus interactives : il permet notamment de faire des menus déroulants. Topo et démos sur les menus déroulants

Sélectionner un élément sur deux

  • Très courant : on a besoin d'appliquer un style à un élément sur deux (typiquement, les lignes d'un tableau)
  • Solution classique : utiliser deux classes différentes (.sombre et .clair)
  • Depuis CSS3 : pseudo-classes pour sélectionner des élements selon leur rang
  • :nth-child(odd) sélectionne les éléments de rang impair, :nth-child(even) sélectionne les éléments de rang pair

Fils de même type

  • Attention, le comportement de :nth-child peut ne pas être intuitif : img:nth-child(odd) ne sélectionne pas une image sur deux, mais tous les éléments qui sont des fils impairs et aussi des images !
  • c'est la conjonction des deux conditions
  • Pour sélectionner une image sur deux, il faut utiliser img:nth-of-type(odd) ou img:nth-of-type(even)
  • Formellement : :nth-of-type(odd) sélectionne un élément s'il est de rang impair dans la liste des fils de même type de son parent

Sélectionner le premier ou le dernier fils

  • :first-child sélectionne les éléments qui sont le premier fils de leur parent
  • :last-child sélectionne les éléments qui sont le dernier fils de leur parent
  • :first-of-type, :last-of-type premier ou dernier fils d'un type donné

Inverse d'un sélecteur

La pseudo-classe :not(X) permet de sélectionner les éléments qui ne sont pas sélectionnés par le sélecteur X

Elle est surtout utile en combinaison avec d'autres sélecteurs :
  • p:not(.youpi) sélectionne tous les paragraphes qui ne sont pas de classe youpi
  • .toto:not(p) sélectionne tous les éléments de classe toto qui ne sont pas des paragraphes
  • a:not(:visited) sélectionne tous les liens qui ne sont pas déjà visités

On ne peut faire la négation que d'un « sélecteur simple », c'est-à-dire qui ne porte que sur une seule caractéristique (type d'élément, classe, identifiant, ou pseudo-classe), mais pas de combinaison : a:not(.youpi:visited) ne fonctionnera pas

Pseudo-éléments

  • Pseudo-classe : sélectionne dynamiquement un élément du document selon certains critères
  • Pseudo-élément : sélectionne dynamiquement un élément qui n'existe pas en tant que tel dans le document
  • ::first-line : pseudo-élément qui sélectionne la première ligne de texte d'un élément
  • ::first-letter : pseudo-élément qui sélectionne la première lettre d'un élément
  • Attention : vous risquez de rencontrer parfois l'ancienne syntaxe (CSS2) des pseudo-éléments, avec un seul : (comme pour les pseudo-classes).
  • La « nouvelle » syntaxe est supportée partout : il est conseillé de l'utiliser pour bien faire la différence, car pseudo-classes et pseudo-éléments fonctionnent de façon très différente
    • #toto:hover sélectionne toto (s'il est survolé), mais
    • #toto::first-line ne sélectionne pas toto, mais un (pseudo-)fils.

Génération de contenu

  • Les pseudo-éléments ::before, ::after permettent d'insérer du contenu au début ou à la fin d'un élément, grâce à la propriété content
  • Exemple :
    #toto::after {
        content: "je suis le dernier";
    }
    
    ajoute un fils à l'élément d'identifiant toto, qui contient le texte je suis le dernier, et qui est situé après tous les fils de toto.