Les sélecteurs de nœuds
- Les feuilles de styles utilisent des sélecteurs pour filtrer les nœuds sur lesquels appliquer des règles CSS.
- Ces sélecteurs peuvent également être utilisés comme argument aux méthodes JavaScript document.querySelector(selector) et document.querySelectorAll(selector) pour trouver un ou tous les éléments DOM validant le sélecteur.
Les sélecteurs de base
- Sélection selon le type d'élément (spécification du nom de l'élément) : p, input, a...
- Sélection selon la classe de l'élément (nom de la classe préfixée par .) : .className
- Sélection par l'identifiant (attribut id) du nœud (identifiant préfixé par #) : #identifier
- Sélection de tous les nœuds de l'arbre DOM (joker) : *
-
Sélection des éléments avec un attribut de valeur spécifique :
- [attr] : présence de l'attribut attr (quelle que soit la valeur)
- [attr="value"] : attr a pour valeur value
- [attr*="factor"] : attr contient la sous-chaîne factor
- [attr^="prefix"] : attr commence par prefix
- [attr$="suffix"] : attr finit par suffix
- [attr~="value1 value2 ..."] : attr a l'une des valeurs indiquées value1 ou value2 ou ...
Un exemple : un sélecteur sélectionnant les liens hypertextes de classe superLink pointant vers une URL commençant par ``https://example.com" :
a.superLink[href^="https://example.com"]
Les opérateurs d'association
Ces opérateurs permettant de sélectionner des nœuds à proximité d'autres nœuds dans l'arbre DOM :
- A > B sélectionne tous les nœuds descendants directs de nœuds A ; par exemple ol > li ne sélectionne que les items de liste ordonnées
- A B sélectionne tous les nœuds B qui descendent directement ou indirectement de A ; par exemple table * sélectionne tous les nœuds présents dans un tableau (que ce soit les lignes tr ou les cellules td...)
- A + B permet de sélectionner les noeuds B qui suivent immédiatement un élément donné A (voisin direct) ; par exemple ol + ul sélectionne toutes les listes non-numérotées ul qui suivent les listes ordonnés ol.
- A ~ B sélectionne en plus des voisins directs de A tous les voisins suivants de la fratrie
Les pseudo-classes
Les pseudos-classes permettent de sélectionner des éléments selon certaines propriétés implicites transitoires ou durables. Certaines peudo-classes sont spécifiques à certains types de balises. Les pseudo-classes sont toutes introduites par le caractère :.
Nous listons les pseudo-classes les plus courantes :
- :visited cible les liens visités par l'internaute
- :hover permet de modifier le style d'un élément lorsque le pointeur passe par dessus
- :active caractérise un élément dans un état actif, par exemple pour un lien il s'agit du moment entre l'appui de clic sur celui-ci et le relachement du clic
- :focus cible l'élément qui a le focus d'entrée
- :target cible l'élément dont l'identifiant est désigné par le fragment de l'URL (#fragment)
- :valid (contraire :invalid) cible les éléments de formulaire dont le contenu est considéré valide selon les contraintes
- :root désigne l'élément racine de l'arbre DOM (typiquement <html>)
- :checked désigne un élément coché (bouton radio, case à cocher)
☞ Il n'est possible de modifier que la couleur de liens avec la pseudo-classe :visited et l'API JavaScript retournera toujours la couleur d'un lien non-visité avec getComputedStyle() ; cela permet d'éviter à une page d'espionner l'historique des sites visités par un internaute.
Il existe aussi des pseudo-classes relatives au positionnement des éléments dans l'arbre DOM :
- :empty sélectionne les éléments sans descendant dans l'arbre
-
Sélecteurs d'enfants selon leur position :
- :first-child sélectionne chaque premier enfant d'un élément
- :last-child sélectionne chaque dernier enfant d'un élément
- :only-child sélectionne les enfants uniques (équivalent à :first-child:last-child)
-
:nth-child(an+b) sélectionne les enfants (en partant du premier) dont le rang valide l'expression
- Par exemple p:nth-child(2n+1) cible les paragraphes de rang 1, 3, 5... (ce qui peut être noté également p:nth-child(odd))
- p:nth-child(2) ciblera uniquement les paragraphes qui sont enfants en position 2
- :nth-last-child(an+b) joue le même rôle que :nth-child(an+b) sauf que les rangs sont comptés depuis le dernier enfant
- :first-of-type, :last-of-type, :only-of-type, :nth-of-type(), :nth-last-of-type() ont un fonctionnement similaires aux précédents sélecteur décrits à la différence que seuls les élément du type indiqué sont pris en compte. Par exemple p:first-child sélectionne les paragraphes qui sont le premier enfant d'un nœud tandis que p:first-of-type sélectionne les paragraphes qui sont les premiers paragraphes dans leur fratrie (ils peuvent être précédés par des éléments d'autres types)
Les pseudo-éléments
Les pseudo-éléments sont des éléments virtuels qui n'existent pas dans l'arbre DOM et qui sont créés spécialement afin d'entourer certains éléments existants. Les pseudo-éléments sont préfixés par ::.
On peut par exemple ajouter du texte autour d'un élément (ici un lien hypertexte) avec les pseudo-éléments ::before et ::after :
a::before { content: "->"; } a::after { content: "<-"; }
Les pseudo-éléments ::first-letter et ::last-letter permettent de cibler la première lettre (ou dernière lettre) d'un élément. On pourra ainsi par exemple mettre une lettrine pour les paragraphes :
p::first-letter { font-size: 150%; }
Il existe également un pseudo-élément ::first-line sélectionnant la première ligne d'un élément.
::selection cible les éléments faisant l'objet d'une sélection par l'utilisateur.
Les feuilles de style
Une feuille de style est une liste de règles permettant d'appliquer des propriétés stylistiques de rendu à certains nœuds de l'arbre DOM en utilisant des sélecteurs.
Voici un exemple de feuille de style mettant le texte des paragraphes en couleur verte sauf les liens qui sont soulignés et mis en rouge :
p { color:green ; } p::first-letter { font-size: 150%; } p a { color: red; text-decoration: underline; }
Une feuille de style peut être directement intégrée dans la page entre balises <style> dans l'en-tête :
<html> <head> ... <style> p { color: green; } ... </style> </head> <body> ... </body> </html>
Préférablement, elle peut être placée dans un fichier externe lié à la page :
<html> <head> ... <link rel="stylesheet" type="text/css" href="mystyle.css"> </head> ... </html>
On peut spécifier différentes variantes de feuilles de style selon le contexte d'affichage de la page avec l'attribut media. Par exemple <link rel="stylesheet" type="text/css" media="print" href="mystyle-print.css"> indique une feuille de style dédiée pour l'impression. Il est possible d'utiliser les médias suivants :
- all : par défaut
- print : page imprimée (embossed pour les impressions en braille)
- screen : rendu sur moniteur informatique (handeld pour un écran de petite taille, tv pour un téléviseur)
- speech : rendu par synthèse vocale
- braille : utilisation d'un terminal braille
- tty : rendu en console texte
- projection : affichage sur un vidéo-projecteur
Il est possible aussi d'indiquer le style d'un élément directement dans l'élément lui-même avec l'attribut style. Par exemple :
<p style="color: red; font-size: 1.25em; border-top: solid;">Hello CSS!</p>
Spécificité de règles
Certaines règles peuvent posséder un sélecteur qui cible des nœuds communs avec des valeurs de propriétés conflictuelles. Par exemple imaginons la feuille de style suivante :
* { color: black; } a { color: blue; } a.aClass { color: green; } #mylink { color: red; } a[href^="http://example.com/page"] { color: gray; } a[href^="http://example.com"] { color: yellow; }
Pour comprendre quelle règle sera appliquée selon les cas, nous devons considérer les sélecteurs par pouvoir de sélectivité décroissant :
- Un sélecteur sur un identifiant possède le plus fort pouvoir de sélectivité (score de 1000). Ainsi le lien <a id="mylink" href="http://example.com/page">Lien</a> sera affiché en rouge.
- Un sélecteur sur attribut, classe ou pseudo-classe arrive ensuite dans l'ordre de sélectivité (score de 100 pour chaque attribut ou classe indiquée). Ainsi il serait logique que le lien <a href="http://example.com/page">Lien</a> soit affiché en gris. Ce n'est pas le cas car lorsque plusieurs règles sont basés sur un attribut correspondant avec celui de l'élément, c'est la dernière déclarée qui l'emporte. Ainsi la régle basée sur l'attribut href commançant par http://example.com/page ne sera jamais sélectionnée. Le sélecteur sur classe a la même spécificité que celui sur attribut. Ainsi pour le lien <a class="aClass" href="http://example.com/page">Lien</a>, le sélecteur sur attribut l'emporte car spécifié en dernier
- Le sélecteur sur élément (ou pseudo-élement) est moins spécifique (score de 1 pour chaque élément)
- Enfin le sélecteur sur élément joker est le moins spécifique de tous (score nul)
Héritage de propriétés
Certaines propriétés de style sont héritées implicitement du nœud ancêtre dans l'arbre DOM alors que ce n'est pas le cas pour d'autres. Par exemple :
- color est hérité (body { color:read; } permet de mettre en rouge l'ensemble des nœuds descendant de body)
- width n'est pas hérité
Par défaut chaque propriété de style d'un élément a la valeur unset :
- Cela peut signifier que la propriété s'hérite de l'ancêtre dans le DOM ; on peut aussi provoquer ce comportement avec inherit
- Ou alors cela peut indiquer pour les propriétés n'héritant pas que l'on utilise la valeur par défaut ; ce comportement peut être forcé avec initial
Par exemple si l'on ne souhaite pas hériter la couleur de l'ancêtre et utiliser celle par défaut pour un paragraphe, on pourra définir la feuille de style suivante :
body { color: red; } p { color: initial; } //* unset correspondrait à inherit pour color */
Quelques propriétés CSS
Il existe de nombreuses propriétés CSS (plus de 600) que ne nous pouvons pas décrire exhaustivement sur cette page. On pourra se référer aux pages suivantes :
Mise en forme du texte
Nous listons quelques propriétés pour le formatage du texte :
- color : couleur désignée par un nom symbolique (white, black, blue...) ou une valeur RGB (par exemple rgb(0,0,255) désigne une couleur bleue)
- text-align : alignement du texte (left, right, center, justify)
- text-decoration : permet de souligner (underline), barrer (line-through), clignoter (blink) le texte
- text-transform : change la casse du texte (lowercase, uppercase, capitalize)
- text-indent : permet d'indiquer un retrait de début de ligne (par exemple 50px, ou 10% de l'espace...)
-
Propriétés de catégorie font :
- font-family : famille de la fonte sous la forme d'une liste préférentielle ; e.g. "Times New Roman", Times, serif ou Arial, Helvetica, sans-serif
- font-size : taille de la fonte en pourcentage de la taille de la fonte du nœud parent (e.g. 200% pour une fonte deux fois plus grande que le parent) ou alors en valeur absolue (en px ou em par exemple)
- font-style : style de la fonte (normal, italique, oblique)
- font-weight : permet de "graisser" la fonte (normal ou 400, bold/ ou 700, bolder, lighter//)
☞ Pour mettre en forme un passage de texte sans créer un nouveau nœud ayant un impact sur l'affichage ou une signification sémantique (par exemple p), on peut envelopper le texte dans un nœud <span class="myClass"> ... </span> avec une ou plusieurs classes CSS spécifiées. On peut ensuite écrire les règles s'appliquant à ces classes dans la feuille de style.
Taille des composants
La taille des composants peut être contrôlée avec différentes propriétés CSS :
- width pour la la largeur demandée ; max-width pour indiquer une borne maximale à la largeur
- height pour la hauteur demandée ; max-height pour spécifier une borne maximale à la hauteur
- margin pour spécifier une marge externe autour de l'élément (on peut indiquer aussi des marges différentes pour chaque côté avec margin-left, margin-right, margin-top et margin-bottom
- padding permet de configurer la marge externe ; il existe aussi des propriétés individuelles pour les quatre coins (padding-left, padding-right...)
Un élément CSS peut aussi disposer d'une bordure configurable avec la propriété border (et ses spécialisations border-left...). On peut modéliser un élément CSS ainsi :
Une dimension peut être exprimée en différentes unités :
- Des unités absolues : cm, mm, in, pt, pc (pica) ; on a relation 1 in = 2.54 cm = 25.4 mm = 72 pt = 6 p
- em est une unité relative à la taille de la fonte (1 em est la taille courante de la fonte dans l'élément)
- rem est une unité relative à la taille par défaut de la fonte ; le rem reste identique pour tout le document tandis que le em peut changer selon le nœud en fonction des propriétés CSS font-size rencontrées
- px désigne l'unité pixel dont la taille dépend de la résolution de l'appareil affichant le document
- L'unité pourcent (%) permet d'indiquer une dimension en proportion de la dimension du nœud parent. Par exemple avec p { width: 50%; } les paragraphes occupent la moitié de la largeur du parent
- L'unité vw désigne un centième de la largeur de la fenêtre d'affichage. Par exemple avec img { width: 50vw; } une image occupe la moitié de la fenêtre d'affichage en largeur
- L'unité vh désigne de la même façon un centième de la hauteur de la fenêtre d'affichage.
- L'unité vmin est le minimum entre vw et vh (a priori correspond à vw en mode portrait et vh en mode paysage) ; il existe aussi vmax pour le maximum
- L'unité ch désigne la largeur du caractère 0 en utilisant la fonte courante (utile pour dimensionner pour afficher une certaine longueur de texte)
☞ Il faut en générale privilégier les unités relatives plutôt que les unités absolues ce qui permet de réaliser un document s'adaptant aux différentes géométries d'écran ou de feuilles d'impression.
☞ On encapsule généralement les entités dans des conteneurs génériques div. On peut ensuite configurer la taille, les bordures, padding et marges des conteneurs div par règle CSS :
<div class="myDivClass"> <img src="somePicture.jpg" /> <p> Some paragraph of text </p> </div>
Mise en page CSS
Positionnement de conteneurs
Les éléments à positionner sont généralement dans des conteneurs div. On utilise la propriété position pour le positionnement, cette propriété peut prendre les valeurs suivantes :
- static : il s'agit du positionnement par défaut dans le flot de la page
- relative : le positionnement est fait par rapport à l'emplacement par défaut dans le flot avec un décalage indiqué par les propriétés left, right, top et bottom (avec une dimension absolue ou relative).
- fixed : l'élément reste à la même position même en cas de défilement de la page (les propriétés left, right, top, bottom... sont utilisées)
- absolute assure un positionnement absolu dans l'élément parent (contrairement à fixed qui assure le positionnement par rapport à la fenêtre)
- sticky : il s'agit d'un postionnement qui utilise le mode relative jusqu'à un certain niveau de défilement puis qui bascule ensuite en mode fixed avec un positionnement fixe sur la fenêtre
Agencement flexible flex
Le mode d'agencement flex a été introduit en 2009 pour faciliter l'agencement d'une chaîne de conteneurs sur une page.
- Pour utiliser le mode flex, on définit la propriéte display: flex pour le conteneur parent. Par défaut les conteneurs parents se partagent l'espace disponible en colonnes de taille égale.
- On peut modifier la propriété flex-direction (axe principal) par défaut à row (positionnement par ligne) ; on peut aussi réaliser un positionnement selon un axe colonne avec column.
- Il est possible de demander l'utilisation de plusieurs lignes/colonnes si le nombre et la taille des composants enfants l'exigent avec flex-wrap: wrap.
- On peut distribuer l'espace inéquitablement entre composants avec la propriété flex sur les composants enfants. Par exemple si l'on dispose de deux composants enfants, l'un avec flex: 1 et l'autre avec flex: 2, le deuxième utilisera deux fois plus d'espace que le premier. Il est aussi possible d'indiquer une dimension minimale (par exemple de 300px) avec flex: 1 300px
- On peut modifier l'ordre des éléments (sans modifier l'ordre dans l'arbre DOM) avec la propriété order. Par défaut tous les éléments ont une propriété order: 0 ; les éléments sont affiché par order croissant, les éléments de même order étant départagés selon leur ordre dans l'arbre DOM.
- On peut aligner les éléments selon l'axe secondaire (par exemple la colonne si flex-direction est fixé à row) avec align-items. Les valeurs possibles sont stretch pour étendre la taille des éléments enfants à la taille du plus grand élément, center pour centrer, start et end pour aligner sur le début ou la fin.
- justify-content aligne les éléments sur l'axe principal avec les valeurs start et end (pour le début et la fin de l'axe), center pour le centrage, stretch étire les composants selon leur propriété flex, space-evenly rajoute de l'espace équitablement au début, à la fin et entre les composants tandis que space-between ne garde pas d'espace au début et à la fin du conteneur (space-around adopte une approche intermédiaire en gardant un peu d'espace avant le premier et après le dernier composant mais pas autant qu'entre les composants)
On pourra consulter ces pages intéressants pour en savoir plus sur l'agencement flexible en CSS :
Agencement grid
Le mode d'agencement grid (display: grid) a été introduit à partir de 2017 pour disposer les éléments sur une grille avec de nombreuses propriétés CSS utilisables pour personnaliser le rendu.
Voici quelques propriétés CSS utilisable pour configurer la grille :
.container { display: grid; /* une colonne de longueur 100px, 200px, 300px */ grid-template-columns: 100px 200px 300px; /* une colonne de 100px de large puis deux autres se partageant l'espace (avec 100px minimum garantis pour la 2ème) */ grid-template-columns: 100px minmax(100px, 1fr) 1fr; /* repeat permet de répeter plusieurs fois des directives (ici 7 fois des colonnes de taille entre 100px et 1fr) */ grid-template-columns: repeat(7, minmax(100px, 1fr)); /* avec auto-fill, on ajoute autant de colonnes que le container parent peut en supporter */ grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); /* à la différence d'auto-fill, auto-fit enlève les colonnes vides */ grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); /* on peut rajouter une gouttière entre les colonnes et lignes */ gap: 10px; /* on peut imposer une taille pour chaque rangée (ici minimale de 100px, auto s'adaptant à la hauteur des éléments dans la rangée) */ grid-auto-rows: minmax(100px, auto); /* il est possible de nommer les lignes et colonnes pour le placement des éléments (. indique une zone vide sans nom) */ grid-template-areas: "title title title" "menu1 content ." "footer foorter footer";
On peut placer un élément sur la grille en indiquant le nom de son area (si on a utilisé grid-template-areas) :
h1 { grid-area: title; /* on peut aligner horizontalement l'item sur le début, la fin, le centre ou étendre sur toute la zone */ justify-self: start | end | center | stretch; /* on peut choisir comment aligner l'item verticalement */ align-self: start | end | center | stretch; }
On peut aussi indiquer explicitement les numéros de colonnes et lignes de placement (les colonnes et lignes sont numérotées depuis 1) :
.something { grid-row: 1; /* placement sur la 1ere ligne */ grid-column: 1 / 4 /* placement sur les colonnes 1 à 4 exclues (donc 1, 2 et 3) */ }
Sans indication, les éléments sont placés sur la première ligne jusqu'à remplir toutes les colonnes, puis sur la deuxième...
Il est possible de positionner les lignes ou colonnes en mode masonry :
- On utilise la propriété grid-template-rows: masonry pour les lignes ou grid-template-columns: masonry pour les colonnes
- En mode masonry, les lignes ou colonnes ne sont plus alignées et s'adaptent à la taille des items contenus
- Le mode masonry est une fonctionnalité expérimentale implantée pour l'instant que sous Firefox et nécessitant une activation manuelle
- Des alternatives existent (plus compliquées) pour arriver au même résultat en utilisant par exemple des bibliothèques JavaScript
Pour en savoir plus sur le positionnement grid :
Transitions CSS
-
Les propriétés CSS appliquées au cours du temps à un nœud de l'arbre DOM peuvent évoluer :
- Car certains attributs du nœuds changent et entraînent l'application de règles CSS différentes
- Ou alors par changement de style ou de classe CSS de l'élément déclenché par du code JavaScript
- Par défaut les changements sont immédiats
- Pour plus d'esthétisme, on peut appliquer une transition : le changement se fait progressivement sur un laps de temps
- Les transitions, c'est beau mais il ne faut pas en abuser
-
On utilise la propriété CSS transition qui peut être décomposée en plusieurs sous-propriétés :
- transition-property indique sur quelles propriétés CSS (séparées par des virgules) la transition doit être réalisée (font-size, opacity, left, top, right, bottom)
- transition-delay indique le temps à attendre entre le changement de la propriété et le début de la transition (par défaut 0s pour une transition qui commence immédiatement)
- transition-duration indique une durée pour la transition (par exemple 2s ou 2000ms de façon équivalente)
-
transition-timing-function indique la fonction de progression de la transition
- par défaut ease : la vitesse de transition augmente puis ralentit vers la fin
- linear : la vitesse de transition est constante
- Il existe d'autres fonctions utilisables ; on peut aussi créer sa propre fonction avec cubic-bezier
Les préprocesseurs CSS
Le rôle de préprocesseurs CSS est de proposer une nouvelle syntaxe plus puissante pour exprimer des feuilles de style. Chaque préprocesseur a ses spécificités ; leur objectif général est d'éviter la duplication de code. Par exemple on pourra trouver des fonctionnalités telles que :
- Une syntaxe alternative (par exemple utilisant des blocs indentés à la Python)
- La définition de variables
- Des fonctions permettant de transformer des valeurs
- Des mixins permettant d'intégrer du code CSS paramétrable
- Le support de blocs conditionnels, de boucles
- ...
Parmi les préprocesseurs les plus répandus, on peut citer :
Les feuilles de styles exprimés dans les langages de ces préprocesseurs sont ensuite transpilés en CSS pour être interprétables par les clients web.
Les bibliothèques CSS
- Il existe des bibliothèques CSS proposant des classes prédéfinies pour répondre aux besoins courants.
- Cela permet de réduire le volume de règles CSS à écrire
-
Quelques bibliothèques :
- Bootstrap : bibiliothèque développée par Twitter depuis 2011 proposant des feuilles de style pour la réalisation de sites réactifs avec des composants
-
Tailwind : bibliothèque utility-first qui permet de réduire au strict minimum les règles CSS à écrire ; on combine différentes classes CSS définies pour les éléments HTML
- Avantage : utilisation du seul fichier HTML sans règles CSS
- Inconvénient : nécessite de connaître des centaines de classes de la bibliothèque pour les combiner sur chaque élément et arriver à ses fins