Pas à pas

L’exemple qui suit montre la succession de décisions induites par la réalisation d’une mise en page web (assez conventionnelle). Les logiques à l’œuvre sont transposables à tous types de mise en page ; des plus simples aux plus complexes.

L’approche décrite ici est basée sur un contenu fictif. Pour une approche alternative et complémentaire, basée sur une structuration progressive d’un contenu réel, voir un autre processus pratique.

CSS et HTML sont intimement liés par les sélecteurs. Pour attribuer une mise en forme à un élément de la page, il faut pouvoir le sélectionner. On est donc souvent amené à ajuster la structure du HTML (au delà de la stricte sémantique) afin de permettre la sélection de portions de contenus et donc leur mise en forme, en ajoutant des éléments HTML pour englober d’autres éléments, des “wrappers” [to wrap : emballer, englober].

Intention finale

L’exemple se base sur une mise en page standard, qui se décline et s’ajuste sur écran large (desktop) et étroit (mobile).

Première décomposition

On détermine les grands éléments HTML :

Le #header

Les éléments du header sont organisés afin de positionner le logo à gauche et le menu à droite en contexte desktop ; le logo au dessus et le menu en dessous en contexte mobile.

Le module de mise en page approprié est flex, qui permet de répartir les éléments en fonction d’un axe principal (horizontal sur desktop ou vertical sur mobile). Voir la documentation sur flex.

Afin de permettre un espace flexible entre le logo et le menu, les éléments doivent être groupés : logo [espace] menu.
<header id="header">
  <a hef="index.html">logo</a>
  <nav>
    <a hef="page.html">page</a>
    <a hef="page.html">page</a>
    <a hef="page.html">page</a>
    <a hef="page.html">page</a>
  </nav>
</header>
#header {
  display:flex;
  justify-content: space-between; 
  /* largeur maximale + centrage */
  max-width: 1000px;
  margin: 0 auto;
}

Le #splash

La zone “splash” contient une image à laquelle se superpose un titre.

On peut utiliser les règles de position pour superposer le titre à l’image, en laissant se déployer la taille naturelle de l’image (qui déterminera donc la hauteur du #splash). Voir la documentation sur position.

<figure id="splash">
  <img src="fichier.jpg" alt="Une image">
  <figcaption>
    Le titre superposé.
  </figcaption>
</figure>
#splash {
  position: relative;
}
#splash figcaption {
  position: absolute;
  /* pour détacher le titre du bord de l’image*/
  bottom: 20px; 
  right: 20px;
}
Aller plus loin (un petit détail)

Si l’on veut permettre au titre de s’aligner sur la largeur du header, une légère complexification s’impose : un nouvel élément doit être introduit pour déterminer une largeur maximale et un centrage.

<figure id="splash"><img src="fichier.jpg" alt="Une image"><figcaption><p>
      Le titre superposé dans un p.
    </p> 
  </figcaption></figure>
#splash figcaption {
  position: absolute;
  bottom: 20px; 
  /* la figcaption recouvre la totalité de la largeur de l’image */
  right: 0;  
  width: 100%;
}

#splash figcaption p{
  /* largeur max + centrage */
  margin: 0 auto;  
  max-width: 1000px;  
  /* Le texte du paragraphe est aligné à droite.*/
  text-align: right;
}

Si l’on souhaite contraindre la hauteur du #splash et ajuster l’image :

#splash {
  position: relative;
  height: 50vh; /* la moitié de la hauteur de l’écran, par exemple */
}

#splash img {
  height: 100%;
  width: 100%;
  object-fit: cover; /* afin que l’image recouvre le splash */
}

La zone #grid

Cette zone contient un ensemble d’éléments identiques, mis en page sous forme de grille. En contexte desktop, la grille est de deux colonnes, en contexte mobile, une seule colonne. C’est évidemment le module CSS grid qui permet de le mettre en page. Voir la documentation sur grid.

<section id="grid">
  <article></article>
  <article></article>
  <article></article>
  …
</section>
#grid {
  display: grid;
  grid-gap: 40px;
  /* deux colonnes */
  grid-template-columns: 1fr 1fr;
  /* largeur maximale + centrage */
  max-width: 1000px;
  margin: 0 auto;
}
/* ci-dessous, une media-query qui affecte une seule colonne */
/* à la grille si le viewport est moins large que 600px */
@media (max-width:600px){
  #grid { grid-template-columns: 1fr; }
}

Chaque élément de la grille, positionné grâce à leur parent #grid, peut alors faire l’objet des mêmes règles pour sa structuration interne.

Pour associer deux éléments sur une même ligne, la même stratégie que pour le #header peut être mise en œuvre: regrouper les deux éléments dans un “wrapper” et lui attribuer un display: flex.

<article>
  <figure>
    <img src="fichier.jpg" alt="*">
  </figure>  
  <header>
    <h1>Titre</h1>
    <p>date</p>
  </header>
  <p>
    Texte
  </p>
</article>
article figure {
  height: 250px;
}
article figure img {
  height: 100%;
  width: 100%; 
  object-fit: cover;
}
article header {
  display: flex;
  justify-content: space-between;
}

Le #footer

Enfin, le pied de page peut être structuré de manière très simple, à nouveau grâce à display: flex.

<footer id="footer">
  <a href="#">lien</a>
  <a href="#">lien</a>
  <a href="#">lien</a>
</footer>
#footer{
  padding:2em;
  display: flex;
  justify-content: center;
}
/* ci-dessous, une media-query qui permet d’organiser les éléments sur une colonne, */
/* et non plus sur une ligne, si le viewport est moins large que 600px */
@media (max-width:600px){
  #footer { flex-direction: column }
}

L’ensemble des règles décrites ci-dessus est rassemblée dans l’exemple accessible ci-dessous.

Quelques propriétés complémentaires ont été ajoutées, principalement pour gérer les espaces blancs (padding et margin) des éléments.

Exemple complet