Leçon 10 : Feuilles de style

Leçon Progress:

Objectifs

Autant HTML se décline en versions, la dernière étant la 5, qui chacune englobe tout le langage, autant CSS, les Cascading Style Sheets (feuilles de style en cascade) sont faites de couches qui se complètent et que l’on peut grossièrement résumer ainsi :

  1. la norme CSS 1 qui pose le principe des propriétés dans la préhistoire du web
  2. la norme CSS 2 puis 2.1 qui introduise les sélecteurs et le modèle de boîte, c’est la référence utilisée qui manière incontournable dans tous les sites
  3. la norme CSS 3 qui apporte des améliorations « cosmétiques » mais qui permettent de nombreux effets modernes : ombres, animations, dégradés, etc, mais aussi, par vagues successives, des améliorations décisives, adoptées petits à petits par les navigateurs, comme Flexbox et très récemment Grid Layout.

Dans ce cours, nous ne traitons que la version 2.1 et de Flexbox, et c’est bien suffisant pour démarrer !

Feuilles de styles

La façon d’appliquer un style à un élément vu dans le leçon précédente n’est pas la seule et n’est pas la plus recommandable. Cette technique d’intégration directe dans le code, au plus prêt des éléments, présente deux défauts majeurs :

  1. la lourdeur car si par exemple toutes les images ont une marge, il faut appliquer ce style à chaque élément <img> dans le code HTML
  2. le manque de souplesse, la structure HTML étant intimement imbriquée aux styles, il est difficile de changer simplement tout l’habillage graphique

La solution consiste en une séparation stricte entre balises HTML et styles, selon deux modalités : les styles sont placés dans l’entête <head> de la page (bien pour le point 1 mais pas pour le 2) ou les styles sont placés dans un fichier à part, une feuille de style, ce qui résout tous nos problèmes.

Nouvelle difficulté avec cette séparation : comment relier les styles aux éléments HTML ? La solution passe par l’écriture de directives où un sélecteur d’éléments permet d’associer des styles à tous les éléments vérifiant ce sélecteur :

Un sélecteur désigne un ensemble d’éléments cibles. Dans cette illustration, tous les éléments <h1> dans le code HTML sont visés par ces deux directives.

Sélecteurs

Un sélecteur peut prendre une grande variété de formes. En voici les principales résumées dans ce tableau.

sélecteur éléments ciblés exemple
*  tous les éléments
tag  tous les éléments de nom tag img sélectionne toutes les images
.classe tous les éléments qui ont l’attribut class="classe" .grand_titre sélectionne par exemple <h1 class="grand_titre">, comme <h3 class="grand_titre">
#identifiant l’élément qui a l’attribut id="identifiant", en principe il ne peut y en avoir qu’un seul #menu sélectionne par exemple <nav id="menu">
sélecteur1 sélecteur2 les éléments qui vérifient sélecteur2 et sont descendant d’un élément vérifiant sélecteur1 .titre img sélectionne les images qui sont descendants d’un élément ayant titre comme classe

h1 strong sélectionne tous éléments <strong> descendant de <h1>

sélecteur1>sélecteur2 les éléments qui vérifient sélecteur2 et sont enfants d’un élément vérifiant sélecteur1 .titre>img sélectionne les images qui sont enfants d’un élément ayant titre comme classe

h1>strong sélectionne tous éléments <strong> enfant de <h1>

 sélecteur1,sélecteur2  les éléments vérifiant sélecteur1 et les éléments vérifiant sélecteur2  h1,h2 cible tous les <h1> ainsi que tous les <h2>

Il existe d’autres sélecteurs d’un usage plus rare. Je vous conseille vivement de consulter et de conserver ce mémento CSS très pratique. Pour une liste exhaustive des sélecteurs, MDN est toujours là.

Stratégie de sélection

Comment savoir quel type de sélecteur choisir ?

C’est vrai que la présentation ci-dessus est assez neutre, listant les principales possibilités. En fin de cours, nous détaillerons les meilleures pratiques en matière de CSS. Pour l’instant, retenons les points suivants.

Sélection par le type d’élément

C’est un sélecteur assez radical, par exemple avec a tous les liens sont ciblés. Souvent pratique si on est sûr que le style devra s’appliquer à tous ces éléments, ce sélecteur peut s’avérer pas assez discriminant. Pour cela, la technique du descendant peut être utiliser. Par exemple vous avez identifié un menu unique par <nav id="menu">. Pour cibler tous les liens qui se trouvent à l’intérieur, on emploie le sélecteur #menu a (le sélecteur plus restrictif « > » est moins utilisé, car il suffit d’insérer un élément entre les deux pour casser les CSS).

Classiquement, ce sélecteur est utilisé pour <body>, qui est unique par nature, pour par exemple désigner une police pour tout le document ou une couleur de fond :

body {
   font-size: 12px;
   background-color: #202020;
}

Sélection par l’identifiant

Identifier un élément en lui attribuant un nom unique dans tout le document sert avant tout pour les ancres et pour le code Javascript. Nous pouvons aussi attribuer un identifiant dans le seul but d’appliquer un ensemble de styles, mais à condition que cette mise en forme ne s’applique qu’à cet endroit.

Voici un exemple classique avec un menu de navigation contenant des styles (display) que nous verrons dans quelques temps :

<head>
   <title>Ma page</title>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <style>
      #menu {
         /* on enlève la puce */
         list-style-type: none;

         /* le bloc ne doit plus prend toute la largeur */
         display: inline-block;

         border: 2px solid #ce1030;

         /* on enlève la marge intérieure de la liste */
         padding: 0;
      }
      #menu li {
         /* on espace les éléments du menu verti. */
         margin: 0.5em;
      }
      #menu a {
         text-decoration: none;
         color: #e02020;
      }
   </style>
</head>
<body>
   <nav>
      <ul id="menu">
         <li>
            <a href="#">Accueil</a>
         </li>
         <li>
            <a href="#">Qui sommes-nous ?</a>
         </li>
         <li>
            <a href="#">Je veux sortir !</a>
         </li>
      </ul>
   </nav>
</body>

Ici, le bloc conteneur du menu et une liste <ul>, qui est une façon classique de représenter un menu, en enlevant les puces et en mettant en forme le tout. Plutôt que de cibler l’élément ul, nous choisissons de lui donner un identifiant et de s’en servir pour les styles. Aucun autre élément ne devra avoir id="menu".

Sélection par la classe

Prenons l’exemple de trois sections qui se suivent et ont la même mise en forme : une bordure noire fine,  une couleur de fond et une marge tout autour. Il est dommage de les identifier individuellement et de répéter les mêmes styles dans trois déclarations :

<head>
   <style>
      #bloc1 {
         margin: 1em;
         border: 1px solid black;
         background-color: #8020ff;
      }
      #bloc2 {
         margin: 1em;
         border: 1px solid black;
         background-color: #8020ff;
      }
      #bloc3 {
         margin: 1em;
         border: 1px solid black;
         background-color: #8020ff;
      }
   </style>
</head>
<body>
   <section id="bloc1"></section>
   <section id="bloc2"></section>
   <section id="bloc3"></section>
</body>

Autant utiliser une classe pour factoriser ces styles :

<head>
   <style>
      .bloc {
         margin: 1em;
         border: 1px solid black;
         background-color: #8020ff;
      }
   </style>
</head>
<body>
   <section class="bloc"></section>
   <section class="bloc"></section>
   <section class="bloc"></section>
</body>

Ce sélecteur est privilégié car il offre beaucoup de souplesse et réduit le code CSS. Il faut tout de même créer des classes au nom judicieux et faire attention au nommage qui peut très vite rendre assez incompréhensible une feuille. Là aussi, ce sujet sera traité en profondeur dans le dernier chapitre.

Notons qu’il faut éviter un nom qui fait référence à une mise en forme car cela manque de généralité et peut changer. Par exemple pour un cadre rouge, évitez le nom « cadre_rouge » (les espaces sont interdits dans un nom de classe, on utilise « _ » ou « -« ). Préférez un nom qui fait référence au rôle, au sens du bloc dans votre zoning. Par exemple article ou encore titre-article.

J’ai prévu une petite leçon à la fin sur les stratégies d’utilisation des sélecteurs. Pas facile de choisir judicieusement entre sélecteurs d’éléments, par identifiant ou par classe. Disons, à ce stade, que :

  1. la classe qui est réutilisable est à privilégier même si elle est utilisée une seule fois
  2. l’identifiant est à réserver à des cas assez rare où l’élément est unique mais même là (par exemple #menu) la classe est préférable (.menu)
  3. le sélecteur d’élément est à manier avec précaution, il est très utile dans trois cas précis :
    • pour un élément seul qui ne changera pas (body par exemple)
    • pour réinitialiser les styles de toutes les occurrences d’un élément (ul par exemple pour s’appliquer par défaut à toute les listes)
    • pour cibler un sous élément d’un bloc stylé par un identifiant ou une classe, comme pour le menu plus haut (.menu a par exemple)

Ce dernier point est sujet à polémique. Nous l’aborderons en toute fin pour aller plus loin avec les styles.

Récapitulons maintenant les différents façon de rattacher des styles au éléments HTML.

Incorporation des styles

Incorporation dans les balises

Les styles sont écrit directement dans l’attribut style de l’élément qui les reçoit.

<h1 style="font-family: serif">Titre</h1>
<p style="color:green; font-size:12px">bla bla</p>

Incorporation dans l’élément <style>

Cet élément est enfant de <head> et contient les déclarations avec sélecteurs. Toutes ces déclarations ne s’appliquent qu’au document où elles sont incorporées.

Un exemple est donné plus haut avec les #bloc1, #bloc2 et #bloc3.

Incorporation dans une feuille séparée

La voilà la méthode la plus souple à privilégier. L’avantage est qu’une même feuille peut servir pour plusieurs documents. Nous verrons avec les styles en cascade que l’on peut combiner plusieurs feuilles.

Il faut un fichier texte d’extension css créé à part du document HTML. En général dans le même dossier pour un petit site ou dans un dossier spécial css si on gère plusieurs feuilles.

La feuille est importée dans une page par un <link> placé comme enfant de l’élément <head> :

<head>
   <title>Ma page</title>
   <link rel="stylesheet" type="text/css" href="feuille.css"/>
</head>

L’attribut type est en principe facultatif dans les navigateurs récents. L’adresse de la feuille est bien sûr une URL relative ou absolue qui pointe vers le fichier .css, que vous nommez évidemment à votre guise.

Dans la feuille .css, nous pouvons trouver ce genre de déclaration :

body {
   font-family: serif;
}

a {
   text-decoration: none;
}

Exercice 1

Reprenez l’exercice 2 de la leçon précédente. Le but est simple, remplacer les styles intégrés directement dans la page par des styles placés dans une feuille à part, rattachée à la page par <link>. Ce sera l’occasion de réfléchir aux types de sélecteurs à adopter. Suivez ces principes :

  1. sélecteur d’élément pour des éléments seuls non susceptibles de changer : ici body et h1
  2. sélecteur par identifiant très rare (certains recommandent de ne jamais s’en servir pour des raisons de performance, au profit des classes) : ici on peut pourquoi pas l’utiliser pour l’image centrale
  3. sélecteur par classe pour le reste en cherchant à factoriser et généraliser des ensembles de mise en forme ; ici les paragraphes ont les mêmes styles, il est pertinent de créer une classe « para » par exemple à appliquer à tous

Si comme moi vous trouvez un peu lourd l’extraction des styles, cet outil en ligne peut vous aider : extractcss.com. Le fonctionnement est particulier, il faut coller le code HTML à gauche puis y insérer des identifiants ou des noms de classes placés sur les éléments (sinon rien ne se passe !). A droite les classes CSS sont créées avec les directives à l’intérieur, il reste à modifier ce code CSS. Ensuite, pour enlever les styles incorporé, il y a html-cleaner.com. Si vous trouvez un outil en ligne qui fait les deux, envoyez-moi l’adresse !

Exercice 2

Poursuivons avec la page Company. Maintenant que la feuille de style est créée, utilisons-là pour changer quelque peu l’aspect sans toucher au code HTML. Le résultat doit donner ceci :

Voici les styles à appliquer :

  1. la page n’a plus de marge, il faut cibler body qui a une marge par défaut
  2. le titre est rouge et sans gras
  3. le bloc de titre en vert foncé a un espacement intérieur qui fait que les images intérieures ne sont plus collées au bord
  4. les images dans les paragraphes ont une bordure colorée, nous voyons juste après cette propriété CSS qui s’écrit : border: 2px solid red

Styles en cascade

Cascade

Il y a trois façon d’appliquer une propriété CSS à un élément : directement dans le code, dans la balise style et dans une feuille à part. Les deux derniers cas font intervenir un sélecteur pour relier la propriété avec un élément. Il est en résulte qu’un élément HTML particulier peut recevoir plusieurs styles contradictoires pour la même propriété. Par exemple une lien <a> peut recevoir une couleur de texte associé à son nom d’élément <a> mais aussi une autre associée à une classe CSS qu’il possède. Finalement, avec quelle couleur va-t-il s’afficher ?

Des règles précises s’appliquent pour qu’il n’y ait jamais d’ambiguïté. Une façon de les décrire consiste à partir d’un élément et à classer par priorité les façons de recevoir un style. C’est celle, effectivement utilisée, de plus grande priorité qui surclassera les autres. Voici ces règles, en commençant par les plus prioritaires.

  1. style marqué !important, une mention que l’on place à la fin d’une directive avant le point-virgule, par exemple color:red !important;
  2. style intégré à l’élément dans le code HTML par l’attribut style
  3. style associé par un sélecteur, dans l’ordre de priorité : identifiant, classe, élément
  4. en cas d’égalité, le dernier style déclaré par la balise style, que ce soit directement dans la balise et dans une feuille, l’emporte

Prenons un exemple parlant :

<!DOCTYPE html>
<html lang="fr">
   <head>
      <title>Ma page</title>
      <meta charset="utf-8">
      <style>
         p {
            color: red;
         }
         #p1 {
            color: green;
         }
         .para {
            color: gray;
         }
      </style>
      <style>
         #p1 {
            color: yellow;
         }
      </style>
   </head>
   <body>
      <p id="p1" class="para">lorem</p>
      <p class="para">lorem</p>
      <p class="para" style="color:purple">lorem</p>
      <p>lorem</p>
   </body>
</html>

La couleur mauve est la plus prioritaire (règle n° 2), elle est donc appliqué au 4è paragraphe. Ensuite, dans l’ordre des priorités, on trouve les sélecteurs par identifiant. C’est le cas du 1er paragraphe qui est donc jaune, car deux déclarations #p1 existent et c’est la dernière qui prévaut. Vient après le sélecteur de classe, celui du 1er est dépassé par l’identifiant, celui du 3è est dépassé par le style direct, par contre il s’exprime dans le 2è où la couleur est donc grise. Enfin, le dernier paragraphe est rouge car c’est le sélecteur p qui définit sa couleur.

La couleur du texte des paragraphes, selon leur numéro d’ordre, est :

  1. jaune
  2. style associé par un sélecteur, dans l’ordre de priorité : identifiant, classe, élément
  3. en cas d’égalité, le dernier style déclaré par la balise style, que ce soit directement dans la balise et dans une feuille, l’emporte

Héritage

En deuxième mécanisme d’application des styles, que nous avons déjà évoqué, il y a aussi l’héritage. Rappelons simplement qu’un élément reçoit les styles hérités de tous ces ancêtres, le plus proche prévalant sur les plus anciens. En général, seules les propriétés de texte, comme la couleur ou la taille de police, sont héritées. Ainsi, par exemple, un paragraphe situé dans body prend la couleur définie dans body, a moins que la couleur soit redéfinie au niveau du paragraphe.

Il y a des situations de priorité qui ne sont pas couverte par les règles édictées plus haut, par exemple avec des sélecteurs multiples comme p > img. On peut résumer la philosophie des ces règles d’application comme ceci :

Pour un élément, s’il y a plusieurs valeurs déclarée pour une même propriété CSS, celle qui remporte la mise est la plus proche et la plus spécifique. C’est ainsi par exemple que l’on considère un identifiant plus spécifique qu’un sélecteur d’élément et que le style dans l’attribut style est prioritaire car très proche de l’élément.

Allez, entraînez-vous un peu sur cet exemple. Vous pouvez chercher mentalement puis tester le code dans un navigateur. Les outils de développeur sont très utiles à ce stade (bouton droit, Examiner l’élément ou touche F12). Vous pouvez voir l’arborescence du document HTML et en cliquant sur un élément voir les styles qui s’y appliquent dans la fenêtre de droite. Cette fenêtre montre les multiples déclarations de styles, par ordre de priorité, qu’elles s’appliquent directement ou qu’elles soient héritées. Les directives « étouffées » sont barrées. Vous pouvez cliquer sur la flèche en haut à droite puis sélectionner un bloc dans la partie visuelle du navigateur.

Exercice 3

Répondez aux questions à partir du code suivant, sans le tester dans un navigateur mais en appliquant mentalement les règles vues plus haut. Passez au test si vraiment vous avez un doute.

<!DOCTYPE html>
<html lang="fr">
   <head>
      <title>Ma page</title>
      <meta charset="utf-8">
      <style>
         p {
            color: yellow;
         }
         
         .para {
            color: blue;
         }
         
         .para span {
            color: green;
         }
         
         span {
            color: red;
         }
         
         p:last-child {
            color : gray;
         }
      </style>
   </head>
   <body>
      <section class="info">
         <p class="para">
            Lorem <span>ipsum</span>
         </p>
         <p>
            Lorem <span>ipsum</span>
         </p>
         <p>
            Lorem <span>ipsum</span>
         </p>
      </section>
   </body>
</html>
  1. Quelle est la couleur du premier, deuxième et troisième « Lorem » ?
  2. Quelle est la couleur du premier, deuxième et troisième « ipsum » ?
  3. Comment faire en sorte, par un style, que tous les span soient rouge, peut importe les autres déclarations CSS ?

Styles par défaut

Dernier point avant de se quitter dans cette longue leçon sur les feuilles de style. Comme nous l’avons écrit, chaque propriété CSS a une valeur par défaut qui s’applique en l’absence de toute déclaration. Par exemple la couleur du texte est fixée à black.

En cascade nous allons pouvoir changer plusieurs fois une propriété, par exemple passer la couleur à red pour body puis à green pour les paragraphes. Si, pour un certain élément, nous voulons revenir à la valeur par défaut sans forcément la connaître, il suffit d’employer le mot clé initial comme valeur, par exemple color: initial.

Enfin, sachez que la plupart des balises ont un aspect visuel définie par la norme, en l’absence de tout style fourni par le développeur. Par exemple un titre h1 est écrit en grand avec des marges. Ceci est toujours défini par des directives CSS par défaut, que l’on peut changer en les redéclarant. Voici par exemple les directives par défaut pour h1 :

h1 {
    display: block;
    font-size: 2em;
    margin-top: 0.67em;
    margin-bottom: 0.67em;
    margin-left: 0;
    margin-right: 0;
    font-weight: bold;
}

Source très utile pour cette question : https://www.w3schools.com/tags/tag_hn.asp

Si vous voulez dans votre page supprimer la marge et le gras du titre, écrivez simplement dans une feuille :

h1 {
    margin: 0;
    font-weight: normal;
}
A retenir

 

Ressources utiles
Téléchargements
Pour aller plus loin

Laisser un commentaire