Les bases
Mise en pratique
Approfondir
TP Responsive
TP Avancé
TP Restaurant : L'en-têteRéservé aux membres premiums
42 min
TP Restaurant : Bloc présentationRéservé aux membres premiums
38 min
TP Restaurant : MenuRéservé aux membres premiums
40 min
TP Restaurant : RéservationRéservé aux membres premiums
32 min
TP Restaurant : Recettes & planRéservé aux membres premiums
37 min
TP Restaurant : FooterRéservé aux membres premiums
17 min
TP Restaurant : Page recetteRéservé aux membres premiums
42 min
Aller plus loin

Aujourd'hui nous n'allons pas forcément voir quelque chose de très complexe mais nous allons essayer de réfléchir à un problème simple en CSS. Comment espacer plusieurs éléments au sain d'une section ?

Approche1 : Marge sur l’élément

La première approche, qui semble la plus naturelle, serait d'utiliser une marge directement sur les éléments que l'on souhaite espacer.

.card {
   …
   margin: 1.5rem 0;
}

Cette méthode va avoir plusieurs inconvénients :

  • Les marges de l'élément vont créer un espace non désirable si le conteneur a des marges intérieures.
  • Si l'élément parent est en display:flex, dans ce cas-là la fusion des marges ne s'opérere plus.
  • Si on souhaite utiliser cet élément dans une grille il faudra retirer les marges pour éviter (ce qui implique de rajouter des styles supplémentaires).
  • On mélange ici apparence et structure, ce qui nuit à la réutilisation du style.

Approche 2 : Des classes utilitaires

Le problème de la première approche est qu'elle n'est pas assez spécifique, elle va appliquer des marges sur tous les éléments .card par défaut.
Pour remédier à ce problème on pourrait être tenté d'utiliser une approche utilitaire qui consiste à utiliser une règle CSS spécifique pour l'ajout de marges.

.mt {
  margin-top: 2rem;
}

Il sera alors possible de réutiliser cette classe dès que l'on aura besoin de rajouter une marge entre plusieurs éléments (et ce quelque soit l'élément).

<div class="card">...</div>
<div class="card mt">...</div>
<div class="alert mt">...</div>

Cette approche est plus intéressante parce qu'elle permet de séparer l'apparence et structure aais apporte aussi son lot de problèmes :

  • Lorsque vous construisez votre structure HTML vous devez penser à l'apparence qu'auront vos éléments (Par exemple vous devrez ajouter de la logique dans les boucles de vos templates pour ajouter ou non la classe utilitaire).
  • Pour des éléments responsive vous allez devoir peut-être rajouter différentes classes pour gérer les différents positionnements ce qui va rendre le code difficile à écrire.
<div class="card">...</div>
<div class="card small-mt large-mt0 medium-mt2">...</div>
<div class="card small-mt large-mt0 medium-mt2">...</div>

Approche 3 : Grid

Le système de grille CSS nous permet de résoudre le problème d'espacement grâce à la propriété grid-gap qui permet d'insérer un espace régulier entre chaque élément. On commencera alors par entourer nos éléments :

<div class="stack">
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>

Et ensuite on utilisera le système de grille pour générer l'espace et l'empilement.

.stack {
  display: grid;
  grid-template-columns: 1fr;
  grid-gap: 1.5rem;
}

Avec ce système, c'est l'élément parent qui est chargé de contrôler la disposition des enfants ce qui offre beaucoup plus de contrôle et permet de ne plus avoir à s'occuper de la structure au niveau des éléments enfants. En revanche le système de grille ne permet pas de gérer simplement des variations au niveau des espacements (il n'est pas possible de diminuer ou augmenter facilement la marge entre 2 éléments).

Approche 4 : Le sélecteur > et +

La précédente approche nous a permis de comprendre que piloter l'espacement par le parent est une très bonne solution à adopter. En revanche on veut pouvoir piloter facilement l'espace entre 2 éléments si nécessaire.

.stack > * + * {
    margin-top: 1.5rem;
}

Cette approche permet d'insérer automatiquement une marge en haut des éléments adjacents à un autre élément et qui sont des enfants direct de l'élément .stack. L'inconvénient est qu'il est alors nécessaire de retirer la marge dès que l'on change de disposition ce qui complique la gestion du responsive.

@media only screen and (min-width: 500px) {
    .stack {
        display:grid;
    }
    .stack > * + * {
        margin-top: 0;
    }
}

Pour se sortir de cette situation il est possible de se reposer sur l'utilisation des variables CSS qui permettent, grâce au système de cascade, de changer dynamiquement l'espace qu'il y a entre les différents éléments depuis le parent.

.stack {
  --space: 1.5rem;
}

.stack > * + * {
    margin-top: var(--space);
}

@media only screen and (min-width: 500px) {
  .stack {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 30px;
    --spacce: 0;
  }
}

Cette variable permet aussi à un élément de contrôler son espacement par rapport aux éléments adjacents. Par exemple si une alerte a besoin d'être plus espacée que le reste :

.alert,
.alert + * {
    --space: 3rem;
}

ou même de gérer simplement des déclinaisons

.stack.large {
    --space: 3rem;
}

Cette méthode est intéréssante car elle permet de contrôler simplement la structure des espaces d'une section avec peu de sélecteurs. En revanche, elle implique d'avoir un code HTML simple où tous les blocs sont au même niveau.

Conclusion

A travers cet article nous avons vu différentes manières de gérer l'espacement et les inconvénients de chacunes de ces méthodes. Il faut voir ces différentes approches comme des outils que vous pourrez utiliser suivant la situation.

  • L'approche 1 (margin) conviendra pour des éléments qui ne sont pas réutilisé et qui ont un espacement constant sur tout le site
  • L'approche 2 (utilitaire) conviendra si vous voulez gérer les espacements au cas par cas.
  • L'approche 3 & 4 conviendra pour créer des sections où les enfants doivent tous être espacé et qui doivent pouvoir changer de structure dans le cadre du responsive.