TD CSS

F. Hémery

2021-2022

Objectifs

Une introduction du mécanisme de mise en place de style dans une page HTML.

Références

A la fin de ce TD

Introduction

Un fichier CSS (Cascading Style Sheets) permet d’indiquer les déclarations de styles qui seront appliquées au document HTML afin de séparer le fond de la forme.

Un fichier CSS est utilisé dans un fichier HTML en ajoutant un lien dans l’en-tête :

<link rel="stylesheet" href="styles.css">

Il est possible de placer les déclarations de style directement dans le fichier HTML sans utiliser de fichier extérieur en utilisant la balise <style> :

<style>
  p {
    text-align: center;
     font-weight: bold;
     color: orange;
  }
  header img {
       border: 3px solid gray;
     margin-bottom: 3em;
  }
</style>

Une déclaration de style se compose d’un sélecteur suivi d’un bloc marqué par des accolades de propriétés à appliquer.

Un sélecteur permet de repérer un élément dans un fichier HTML et plus précisément dans le DOM (Document Object Model), la structure de données qui modélise le document HTML dans la mémoire du navigateur.

La notion de cascade et d’héritage

Les propriétés utilisées pour donner une apparence particulière aux éléments qui composent la page HTML récupèrent leur valeur en utilisant le mécanisme de cascade et d’héritage.

  • Cascade
    • Si la propriété est définie plusieurs fois on utilise la dernière définition
    • Si la propriété est définie à l’aide de plusieurs sélecteurs, la valeur donnée dans la déclaration qui utilise un sélecteur plus spécifique sera utilisée.
  • Héritage Certaines propriétés peuvent être héritées d’autres non. Pour les propriétés qui peuvent être héritées, on peut contrôler le mécanisme.

Pour avoir plus d’information, voir la documentation.

Valeurs et unités

Tableau des unités utilisées

Unité Nom Équivalent à
cm Centimeters 1cm = 96px/2.54
mm Millimeters 1mm = 1/10th of 1cm
Q Quarter-millimeters 1Q = 1/40th of 1cm
in Inches 1in = 2.54cm = 96px
pc Picas 1pc = 1/6th of 1in
pt Point 1pt = 1/72th of 1in
px Pixels 1px = 1/96th of 1in

Tableau des unités relatives.

Unité Relative à
em Taille de la font de caractères de l’élément parent, dans le cas d’une propriété typographique comme font-size et la taille de la font de caractères de l’élément lui-même dans le cas d’autres propriétés comme width.
ex x-hauteur de la font de caractères de l’élément.
ch La mesure en largeur (width) du dessin du chiffre “0” de la font de caractères de l’élément.
rem Taille de la font de caractères de l’élément racine.
lh Hauteur de la lignede l’élément.
vw 1% de la largeur du viewport.
vh 1% de la hauteur du viewport.
vmin 1% de la plus petite dimension du viewport entre hauteur et largeur.
vmax 1% de la plus grande dimension du viewport entre hauteur et largeur.

La dimension viewport constitue la partie visible d’une page affichée dans votre navigateur.

Pour avoir plus d’information, voir la documentation.

Les sélecteurs

Un sélecteur utilise une syntaxe pour sélectionner finement un élément dans le DOM.

Utilisation des noms d’élément

Le sélecteur est un nom d’élément.

Utilisation d’un nom de classe

Le sélecteur est une valeur de l’attribut class.

.remarque { }

Utilisation des attributs

  • Sélection sur la présence d’un attribut

    [disabled] {
      cursor: not-allowed;
    }
  • Sélection en fonction de la valeur d’un attribut

    input[type="text"] {
       padding: 2px;
    }
  • Sélecteur d’attribut modulé

    a[rel~="author"] {
      color: hotpink;
    }

    Attribut rel de l’élément a doit contenir la chaîne de caractères “author”.

    a[hreflang|="en"] {
       style: british;
    }

    Attribut dont la valeur est exacte ou démarre par une chaîne de caractères “en” suivie d’un caractère “-”, par exemple en-US, en-EN.

    a[href^="http"] {
        /* Liens externes */
    }

    Attribut dont la valeur débute par une chaîne de caractères “http”.

    a[href$=".pdf"] {
    
    }

    Attribut dont la valeur se termine par une chaîne de caractères “.pdf”.

    [class*="button"] {
       /* Des styles de boutons */
    }

    Attribut dont la valeur contient une chaîne de caractères “boutton”.

Utilisation des opérateurs

  • L’opérateur de sélection d’enfant

    Si plusieurs éléments sont indiqués séparés par un espace, la déclaration s’applique à l’élément enfant (contenu dans) par exemple nav ul { ... } s’applique à tout élément <ul> enfant d’un <nav>.

  • L’opérateur de sélection alternative

    Si une liste d’éléments sont indiqués séparés par une virgule, la déclaration s’applique à chaque élément de la liste par exemple h5, h6 { ... } s’applique à tout élément <h5>ou à tout élément <h6>.

  • L’opérateur de sélection d’enfant direct ‘>

    La déclaration s’applique à l’élément enfant (contenu dans) par exemple ul>li { } s’applique à tout élément <li> enfant direct d’un <ul>.

  • L’opérateur d’adjacence direct ‘+’ et d’adjacence généraliséé ‘~

    La déclaration s’applique à l’élément qui suit immédiatement par exemple :h1+p { } s’applique à tout élément <p> immédiatement précédé par un élément <h1> (voir tableau ci-dessous), ou à l’ensemble des éléments qui suivent par exemple h2~p { } s’applique à un ou plusieurs éléments <p> précédés par un élément <h2>

Quelques exemples

Sélecteur Exemples Éléments concernés
Sélecteur d’élément nav { }
p { }
ul { }
<nav>
<p>
<ul>
Sélecteur de classe .remarque { }
div.remarque { }
Tout élément portant l’attribut class="remarque"
<div class="remarque">.
Sélecteur d’id #intro { }
header#intro { }
Tout élément portant l’attribut id="intro"
<header id="intro">.
Sélecteur d’attribut [alt] { }
input[type=submit] { }
[rel=nofollow] { }
Tout élément possédant un attribut alt
<input type="submit">.
Tout élément portant l’attribut rel="nofollow".
Sélecteur d’enfant direct ul>li { } Tout élément <li> enfant direct d’un <ul>.
Sélecteur d’élément adjacent h1+p { } Tout élément <p> immédiatement précédé par un élément <h1>.
Sélecteur d’éléments frères h2~p { } Un ou plusieurs éléments <p> précédés par un élément <h2>.
Tableau tiré de HTML 5 Une référence pour le développeur web Rodolphe Rimelé

Utilisation des pseudo-classes

La liste complète des sélecteurs de type pseudo-classes est donnée dans la documentation.

Utilisation des pseudo-classes de position

  • Premier et dernier fils

    ul > li:first-child {
       color: red;
    }
    ul > li:last-child {
      border-bottom: solid 1px black;
    }
  • Énièmes enfants avec :nth-child et :nth-last-child

    Permet de sélectionner le énième enfants à partir du début ou à partir de la fin.

    ul > li:nth-child(2) {
       color: red;
    }

    Sélectionne de 2ème fils.

    li:nth-child(2n) {
      background-color: #8dcffc;
    }

    Sélectionne les fils multiples de 2 (à partir de l’indice 0) donc 2, 4, 6….

  • Enfants pair (even) ou impair(odd)

    li:nth-child(even) {
      background-color: #8dcffc;
    }
  • Énièmes éléments de typec :*-of-type

    • nth-of-type ;
    • last-of-type ;
    • first-of-type ;
    • nth-last-of-type ;
    • only-of-type.
    h2:first-of-type {
      color: #0000f1;
    }

Utilisation des pseudo-classes de contexte

Liste des pseudo-classes de contexte non développées ici voir la documentation.

target, empty, blank, root, lang, not(), is()

Utilisation des pseudo-classes de formulaire

  • focus

    input:focus {
      border: 1px solid hotpink;
    }
  • État des champs de formulaire avec :enabled et :disabled

    input:disabled, textarea:disabled, select:disabled {
       background: silver;
       cursor: not-allowed;
    }
  • Modes d’écriture avec :read-write et :read-only

    :read-only {
      background: #EEE;
      opacity: 0.8;
    }
    :read-write { 
      background: white;
    }
  • Validité des champs de formulaire avec :valid et :invalid

    input:invalid {
       background: red;
    }
  • Statut des champs de formulaire avec :optional et :required

  • Statut des champs de formulaire avec :default pour les boutons radio, checkbox, button

    input[type="radio"]:default + label:after {
      content: " (défaut)";
    }
    <div>
        <p>Genre</p>
        <input type="radio" value="homme" name="genre" id="h">
        <label for="h">Homme</label>
        <input type="radio" value="femme" name="genre" id="f">
        <label for="f">Femme</label>
        <input type="radio" value="nc" name="genre" id="nc" checked>
        <label for="nc">Non spécifié</label>
    </div>
  • Gestion de l’amplitude des champs de type number avec :in-range et :out-of-range

    input[type="number"]:in-range { 
      border-color: green;
    }
    input[type="number"]:out-of-range {
      border-color: red;
    }

Utilisation des pseudo-éléments

Déclaration de style pour ce qui précède, ce qui suit, …, l’élément identifié.

  • ::before

  • ::after

  • ::first-line

  • ::first-letter

  • ::selection

  • ::selection {
      color: gold;
      background-color: red;
    }
    
    p::selection {
    color: white;
    background-color: black;
    }
    <div>Un peu de texte pour tester <code>::selection</code>.</div>
    <p>Essayez également de sélectionner du texte dans ce &lt;p&gt;</p>

Positionnement et mise en page

Le modèle de boîte

Voir la documentation pour plus d’information.

  • La hauteur = height + padding-top + padding-bottom + border-top + border-bottom.
  • La largeur = width + padding-left + padding-right + border-left + border-right

Les marges ne sont pas incluses pour calculer la taille de la boite.

Si on définit une classe element avec la déclaration de style suivant

.element {
  width: 200px;
  height: 200px;
  padding: 10px;
  border: 5px solid;
}

On obtient une boite de 230 x 230 = 200 + (10 + 5) * 2.

Si on veut obtenir finalement une boite de 200 x 200, il faut ajouter la propriété box-sizing avec la valeur content-box.

.element {
  width: 200px;
  height: 200px;
  padding: 10px;
  border: 5px solid;
  box-sizing: border-box; /* pour le comportement par défaut box-sizing: content-box */
}

Les boites dans la ligne

Il existe des éléments blocs (l’élément <p> par exemple) et des éléments en ligne (l’élément <span> par exemple). Il est possible d’utiliser une propriété qui va permettre de rester en ligne (sans retour à la ligne) tout en ne surchargeant pas le texte alentour.

span {
  margin: 20px;
  padding: 20px;
  width: 80px;
  height: 50px;
  background-color: lightblue;
  border: 2px solid blue;
}
<p>
    I am a paragraph and this is a <span>span</span> inside that paragraph. A span is an inline element and so does not respect width and height.
</p>

donne

Si on ajoute la propriété display avec la valeur inline-block on obtient le résultat suivant :

Dans ce cas on prend en compte les propriétés width et height de l’élément qui sont ignorées sinon et sans aller à la ligne.

La mise en colonnes du contenu de la page

Voir la documentation pour plus d’information.

Les modèles de boîtes flexibles avec Flexbox

Figure tirée de CSS3 Pratique du design web Hugo Giraudel, Raphaël Goetter, Chris Coyier

Dans le module flexbox on utilise un axe principal et un axe secondaire perpendiculaire au premier.

Définitions reprises du livre CSS3 Pratique du design web :

  • main-start et main-end : les éléments flexibles sont placés sur le main axis de main-start à main-end (pas nécessairement de gauche à droite ni de haut en bas).
  • cross-start et cross-end : les éléments flexibles sont placés sur le cross axis de cross-start à cross-end (pas nécessairement de haut en bas ni de gauche à droite).
  • main-size : la largeur ou la hauteur d’un élément (selon la dimension principale définie par le main axis).
  • cross-size : la largeur ou la hauteur d’un élément (selon la dimension secondaire définie par le cross axis).

Pour gérer les boites avec le module flexbox, il faut ajouter la propriété display et lui donner la valeur flex ou inline-flex. Les éléments du conteneur flex sont des flex-items.

.conteneur {
  display: flex; /* inline-flex pour in conteneur inline */
}

L’utilisation du module flexbox introduit de nouvelles propriétés.

Direction générale avec flex-direction

.conteneur {
  display: flex;
  flex-direction: row | row-reverse | column | column-reverse
}
Figure tirée de CSS3 Pratique du design web Hugo Giraudel, Raphaël Goetter, Chris Coyier

Gestion des retours à la ligne avec flex-wrap

.conteneur {
  display: flex;
  flex-direction: row | row-reverse | column | column-reverse
  flex-wrap: nowrap | wrap | wrap-reverse
}
Figure tirée de CSS3 Pratique du design web Hugo Giraudel, Raphaël Goetter, Chris Coyier

Ou en regroupant les deux :

.conteneur {
  display: flex;
  flex-flow: <'flex-direction'> || <'flex-wrap'>
}

Justification avec justify-content

.conteneur {
  display: flex;
  flex-direction: row
  flex-wrap: wrap
  justify-content: flex-start | flex-end | center | space-between | space-around
}
Figure tirée de CSS3 Pratique du design web Hugo Giraudel, Raphaël Goetter, Chris Coyier

Alignement du contenu avec align-items

.conteneur {
  display: flex;
  flex-direction: row
  flex-wrap: wrap
  justify-content: flex-start
  align-items: flex-start | flex-end | center | baseline | stretch
}
Figure tirée de CSS3 Pratique du design web Hugo Giraudel, Raphaël Goetter, Chris Coyier

Répartition des lignes avec align-content

.conteneur {
  display: flex;
  flex-direction: row
  flex-wrap: wrap
  justify-content: flex-start
  align-items: stretch
  align-content: flex-start | flex-end | center | space-between | space-around | stretch
}
Figure tirée de CSS3 Pratique du design web Hugo Giraudel, Raphaël Goetter, Chris Coyier

Accroissement avec flex-grow

Quand il reste de la place dans la ligne, il est possible de privilégier certains éléments qui vont prendre plus de place que les autres. Par défaut aucun élément n’est privilégié (flex-grow: 0;). De la même façon il y a la propriété de rétrécissement avec flex-shrink.

Figure tirée de CSS3 Pratique du design web Hugo Giraudel, Raphaël Goetter, Chris Coyier

Cette propriété s’applique sur un élément contenu dans un conteneur géré avec flexbox.

Exemple repris du livre CSS3 Pratique du design web

Le modèle de grille

Le modèle de grille représente la page sous la forme de rangées (lignes) qui sont constituées de colonnes. Ce module est utilisé pour gérer le format global de la page (le layout).

Si on souhaite positionner l’utilisation du module grid par rapport au module flexbox, on dira que le module grid est réservé au placement de boites dans la page et que le module flexbox est utilisé pour concevoir le contenu des boites. “La conception par Grid Layout donne la priorité au conteneur tandis que Flexbox laisse la part belle au contenu” (Flexbox ou Grid Layout ?).

Cette approche va permettre de bâtir plus facilement la page. Chaque élément sera un bloc (une zone) dans la page.
Figures tirées de Grid by Example

Pour utiliser le module grid, il faut utiliser la propriété display et lui donner la valeur grid ou inline-grid.

La documentation proposée par Mozilla Developer Network Web Docs sur le module grid est une très bonne introduction.

A la lecture de la documentation vous saurez utiliser le module grid est en particulier les propriétés :

  • grid-template-columns : format des colonnes d’une ligne.
  • l’unité fr : qui permet de donner une taille relative des colonnes.
  • grid-gap ou gap : qui permet de préciser la dimension de la gouttière entre colonnes.
  • grid-auto-rows : qui permet de préciser la hauteur de la ligne par défaut.
  • la fonction repeat(): synthétise la déclaration de la taille des colonnes.
  • la fonction minmax() : permet d’indiquer une fourchette de taille pour la colonne.

Dans un deuxième temps la documentation introduit la notion de placement des boites dans la grille à l’aide des propriétés :

  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end
  • grid-column
  • grid-row

Enfin la propriété grid-template-areas est introduite. Elle permet de nommer les zones dans la page.

Les navigateurs disposent d’un mécanisme d’aide à la conception d’une page

  • Inspecteur > Element > Layout pour chrome
  • Inspecteur > Mise en page > Grilles pour firefox

Utilisation d’un outil de zoning

Lors que l’on développe un site web on passe par plusieurs étapes :

  • Le zoning Pour schématiser les pages web avec des boites ou des blocs pour montrer les principaux contenus et fonctionnalités
  • Le wireframe À partir de l’étape précédente on affine avec du texte, du contenu …
  • Le prototype
    • Rend les pages interactives.
    • Ajoute des liens entre les pages pour donner les principes de navigation du projet.
    • Rend les formulaires fonctionnels.

Pour mettre en place le zoning et le wireframe (fils de fer) on utilisera un outil comme Pencil qui permet à la fois de placer des boites et aussi des éléments html dans une page.

Cette version du site sera proposée au client pour validation avant de créer un prototype.

Exercices

  • Visualiser le modèle de boite
  • Utiliser le modèle de colonne
  • Utiliser l’exercice proposé dans MDN sur flexbox.
  • Modifier et adapter les exemples de grille dans Grid by Example.
  • Tester l’inspecteur de votre navigateur pour visualiser le travail du module grid.
  • Tester l’inspecteur de votre navigateur pour visualiser le travail du module flexbox.
  • Tester l’utilisation de l’outil Pencil.