r202

Structuration d’interfaces en CSS

Généralités

IHM

8 critères :

  • clarté
  • concision
  • familiarité
  • réactivité
  • cohérence
  • esthétique
  • efficacité
  • bienveillance

Problématique

Structuration de l’interface pour différents périphériques.

structure de base de l'application structure de base de l'application structure de base de l'application structure de base de l'application structure de base de l'application structure de base de l'application structure de base de l'application structure de base de l'application structure de base de l'application

Table des matières

  1. Retour sur CSS
  2. Le module « flexbox »
  3. Les « media queries »
  4. CSS et bonnes pratiques

Retour sur le CSS

Flux d’affichage normal

Le flux d’affichage CSS repose sur l’affichage de blocs.

  display: inline;

Initialement, les blocs étaient de 2 types :

  • block,
  • ou inline.

Ensuite est arrivé le type inline-block fusionnant les deux autres types.

Affichage block

Les éléments d’affichage block suivent le comportement des paragraphes.

Affichage block Affichage block

On parle parfois d’axe vertical.

Affichage inline

Les éléments d’affichage inline suivent le comportement du texte.

Affichage inline Affichage inline

On parle parfois d’axe horizontal.

Affichage inline-block

Les éléments d’affichage inline-block suivent le comportement du texte.

Affichage inline-block

Il s’agit toujours de l’axe horizontal.

Sortir du flux

Tous les éléments sont dans le flux d’affichage, sauf :

  • les éléments flottants,
  • les éléments en position fixe ou absolue, (voire collante).

Position des éléments

Par défaut :

position : static;

Mais ils peuvent aussi recevoir comme valeur :

  • relative
  • absolute
  • fixed
  • sticky

La position est ensuite modifiée à l’aide des propriétés top, right, bottom et left.

Position relative

L’élément est positionné dans le flux normal, puis décalé à l’aide de top, right, bottom et left.

span {
  position: relative;
}
span {
  position: relative;
  left: 2em;
  top: 2em;
}
span {
  position: relative;
  left: 2em;
  top: 2em;
  margin: 0 1em;
}
Position relative Position relative Position relative

Attention : nouveau contexte d’empilement z-index.

Position absolute

L’élément est sorti du flux d’affichage. Il est positionné, à l’aide de top, right, bottom et left, par rapport au premier ancêtre positionné.

span {
  margin: 0 1em;
}
span {
  position: absolute;
  left: 2em;
  top: 2em;
}
div {
}
span {
  margin: 0 1em;
}
div {
  position: absolute;
  width: 75%;
  left: 2em;
  bottom: 2em;
}
span {
  margin: 0 1em;
}
div {
  position: absolute;
  width: 75%;
  left: 2em;
  bottom: 2em;
}
span {
  position: absolute;
  left: 2em;
  top: 2em;
  margin: 0 1em;
}
Position absolute Position absolute Position absolute Position absolute Position absolute

Attention : nouveau contexte d’empilement z-index.

Position fixed

L’élément est sorti du flux d’affichage. Il est positionné, à l’aide de top, right, bottom et left, par rapport à la zone d’affichage de la fenêtre.

span {
  margin: 1em;
}
span {
  position: fixed;
  left: 2em;
  top: 2em;
  margin: 1em;
}
Position fixed Position fixed Position fixed

Attention : nouveau contexte d’empilement z-index.

Position sticky

L’élément est positionné dans le flux normal. Mais adhérera au bord de la zone d’affichage en fonction de top, right, bottom et left.

span {
 position: sticky;
 top: 2em;
}
Position sticky Position sticky Position sticky

Attention : nouveau contexte d’empilement z-index.

Exemples de position

Un exemple de positionnement CSS.

p:nth-of-type(3)  {
  position: relative;
  border: 1px solid #88f;
  margin: 3em auto;
  width: 50%;
}
span {
  background-color: #ddd;
  color: #000;
  border: 1px solid #aaf;
  top: 2em;
  left: 2em;
  margin: 1em;
}
.static {
  position: static;
}
.relative {
  position: relative;
}
.absolute {
  position: absolute;
}
.fixed {
  position: fixed;
}
.sticky {
  position: sticky;
  bottom: 2em;
}

Éléments flottants

Syntaxe :

float: left | right | none | inline-start | inline-end;

L’élément est retiré du flux normal et doit être placé sur le côté droit ou gauche du conteneur.

Les éléments en ligne (inline) entourent l’élément.

span {
}
span {
  float: left;
}
span {
  float: right;
}
span {
  float: right;
}
span:nth-child(even) {
  float: left;
}
span {
  float: right;
  width: 2em;
  height: 2em;
}
span:nth-child(even) {
  float: left;
}
éléments flottants éléments flottants éléments flottants éléments flottants éléments flottants

Les clear floats

Syntaxe :

clear: left | right | none | inline-start | inline-end;

Spécifie si l’élément doit être décalé en dessous de l’élément flottant précédent.

span {
}
span {
  clear: left;
}
span {
  clear: right;
}
span {
  clear: both;
}
clear float clear float clear float clear float

Exemples d’éléments flottants

Un exemple d’éléments flottants en CSS.

div {
  border: 1px solid #88f;
  margin: 1em;
  padding: 2em;
  float: right;
}
div:nth-child(even) {
  float: left;
}

z-index

Syntaxe :

z-index: auto | <integer>;

Définit le « z-order » des éléments positionnés.

.un {
  position: absolute;
}
.deux {
  position: absolute;
}
.trois {
  position: absolute;
}
.un {
  position: absolute;
  z-index: 5;
}
.deux {
  position: absolute;
}
.trois {
  position: absolute;
}
.un {
  position: absolute;
  z-index: 5;
}
.deux {
  position: absolute;
  z-index: 2;
}
.trois {
  position: absolute;
}
z-order z-order z-order

Context de z-index

.un {
}
.deux {
}
.trois {
}
.quatre {
}
.cinq {
}
.un {
}
.deux {
  z-index: 5;
}
.trois {
  z-index: 4;
}
.quatre {
}
.cinq {
  z-index: 3;
}
.un {
  z-index: 1;
}
.deux {
  z-index: 5;
}
.trois {
  z-index: 4;
}
.quatre {
  z-index: 1;
}
.cinq {
  z-index: 3;
}
.un {
  z-index: 2;
}
.deux {
  z-index: 5;
}
.trois {
  z-index: 4;
}
.quatre {
  z-index: 1;
}
.cinq {
  z-index: 3;
}
.un {
  z-index: 2;
}
.deux {
  z-index: 5;
}
.trois {
  z-index: 4;
}
.quatre {
  z-index: 1;
}
.cinq {
  z-index: 6;
}
z-order z-order z-order z-order z-order z-order

Exemples de z-index

Un exemple d’utilisation du z-index.

<div class="un">1
  <div class="deux">2</div>
  <div class="trois">3</div>
</div>
<div class="quatre">4
  <div class="cinq">5</div>
</div>
.un {
  z-index: 1;
}
.deux {
  z-index: 5;
}
.trois {
  z-index: 4;
}
.quatre {
  z-index: 1;
}
.cinq {
  z-index: 3;
}

Le modèle de boite

Le modèle de boite HTML est constitué :

  • d’une boite définie par width et height,
  • encadrée par une marge interne, le padding,
  • une bordure (border),
  • et une marge externe : margin.
le modèle de boite

Syntaxe

div {
  margin: 2em;
}
div {
  margin: 1em 2em;
}
div {
  margin: 1em 2em 3em 4em;
}
div {
  padding: 1em;
}
div {
  border-style: solid;
  border-width: 1px 2px 3px 4px;
  border-color: red, blue;
}
div {
  margin-top: 2em;
  margin-right: 2em;
  margin-bottom: 2em;
  margin-left: 2em;
}
div {
  margin-top: 1em;
  margin-right: 2em;
  margin-bottom: 1em;
  margin-left: 2em;
}
div {
  margin-top: 1em;
  margin-right: 2em;
  margin-bottom: 3em;
  margin-left: 4em;
}
div {
  padding-top: 1em;
  padding-right: 2em;
  padding-bottom: 3em;
  padding-left: 4em;
}
div {
  border-top: 1px solid red;
  margin-right: 2px solid blue;
  margin-bottom: 3px solid red;
  margin-left: 4px solid blue;
}

Taille de la boite

Par défaut, width et height définissent la zone interne au padding.

La propriété box-sizing définit ce comportement.

div {
  margin: 20px;
  padding: 20px;
  border: 5px solid #fff;
  width: 100px;
  box-sizing: content-box;
}
div {
  margin: 20px;
  padding: 20px;
  border: 5px solid #fff;
  width: 100px;
  box-sizing: border-box;
}
content-box border-box

Débordement

Le débordement intervient lorsqu’une boite est trop petite pour son contenu, en x, y ou les deux.

Par défaut, le comportement est de déborder de la boite :

le débordement

Syntaxe

La propriété overflow modifie le comportement du débordement :

div {
  overflow: visible;
}
div {
  overflow: hidden;
}
div {
  overflow: scroll;
}
div {
  overflow: auto;
}
débordement débordement débordement débordement

Taille de la boite

Attention, lors de la définition d’une zone « scrollable », une erreur classique consiste à oublier que la taille de la zone doit-être fixée.

Le module « flexbox »

Le concept

Le module « flexbox », est un modèle unidimensionnel permettant d’organiser les éléments d’un conteneur en spécifiant :

  • la distribution,
  • l’espacement
  • et l’alignement.

Il permet aussi d’agir sur chaque élément pour spécifier comment il doit occuper l’espace.

Un conteneur

Le module s’applique à un conteneur et ses éléments fils sont positionnés.

.conteneur {
  display: flex; /* or inline-flex */
}
<div class="conteneur">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</div>
exemple d'organisation en flex exemple d'organisation en flex exemple d'organisation en flex

Axe principal

Le module « flexbox » étant unidimensionnel et l’interface bidimensionnel, il faut choisir un axe principal (row par défaut) :

.conteneur {
  display: flex;
  flex-direction: row | row-reverse | column | column-reverse;
}
.conteneur {
  display: flex;
}
.conteneur {
  display: flex;
  flex-direction: row;
}
.conteneur {
  display: flex;
  flex-direction: column;
}
.conteneur {
  display: flex;
  flex-direction: row-reverse;
}
.conteneur {
  display: flex;
  flex-direction: column-reverse;
}
exemple d'axe principal exemple d'axe principal exemple d'axe principal exemple d'axe principal

Distribution

La distribution des éléments est réalisée sur l’axe principal (flex-start par défaut) :

.conteneur {
  display: flex;
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}
.conteneur {
  display: flex;
}
.conteneur {
  display: flex;
  justify-content: flex-start;
}
.conteneur {
  display: flex;
  justify-content: flex-end;
}
.conteneur {
  display: flex;
  justify-content: center;
}
.conteneur {
  display: flex;
  justify-content: space-between;
}
.conteneur {
  display: flex;
  justify-content: space-around;
}
.conteneur {
  display: flex;
  justify-content: space-evenly;
}
exemple de distribution exemple de distribution exemple de distribution exemple de distribution exemple de distribution exemple de distribution

Alignement

L’alignement des éléments est réalisé sur l’axe secondaire (stretch par défaut) :

.conteneur {
  display: flex;
  align-items: stretch | flex-start | flex-end | center | baseline;
}
.conteneur {
  display: flex;
}
.conteneur {
  display: flex;
  align-items: stretch;
}
.conteneur {
  display: flex;
  align-items: flex-start;
}
.conteneur {
  display: flex;
  align-items: flex-end;
}
.conteneur {
  display: flex;
  align-items: center;
}
.conteneur {
  display: flex;
  align-items: baseline;
}
exemple d'alignement exemple d'alignement exemple d'alignement exemple d'alignement exemple d'alignement

Retour à la ligne

Par défaut, les éléments sont alignés sur une ligne (nowrap par défaut) :

.conteneur {
  display: flex;
  flex-wrap: nowrap | wrap | wrap-reverse;
}
.conteneur {
  display: flex;
}
.conteneur > * {
  width: 3em;
}
.conteneur {
  display: flex;
  overflow: hidden;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  overflow: hidden;
  flex-wrap: nowrap;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  overflow: hidden;
  flex-wrap: wrap;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  overflow: hidden;
  flex-wrap: wrap-reverse;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
exemple d'alignement
exemple d'alignement
exemple d'alignement exemple d'alignement

Distribution des lignes

Par défaut, les lignes sont distribuées régulièrement sur l’axe secondaire (normal par défaut) :

.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: normal | stretch | flex-start | flex-end | center | baseline | space-between | space-around | space-evenly;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-content: normal;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: normal
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: stretch;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-end;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: center;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: baseline;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: space-between;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: space-around;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
.conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: space-evenly;
}
.conteneur > * {
  width: 3em;
  flex-shrink: 0;
}
exemple de distribution de lignes
exemple de distribution de lignes
exemple de distribution de lignes exemple de distribution de lignes exemple de distribution de lignes exemple de distribution de lignes exemple de distribution de lignes exemple de distribution de lignes exemple de distribution de lignes

Espacement

L’espacement entre les éléments peut être géré à l’aide de gap :

.conteneur {
  display: flex;
  gap: 1em;
}
.conteneur {
  display: flex;
  gap: 1em 2em; /* row-gap column-gap */
}
.conteneur {
  display: flex;
  row-gap: 1em;
  column-gap: 2em;
}
espacement des éléments

Alignement d’un élément

L’alignement peut être spécifié par élément :

.conteneur {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.conteneur > *:nth-child(even) {
  align-self: stretch;
}
.conteneur > *:nth-child(2) {
  align-self: center;
}
Exemple d'alignement des éléments

Ordre des éléments

Il est possible de donner l’indice d’un élément dans son conteneur (0 par défaut) :

.conteneur {
  display: flex;
  justify-content: stretch;
}
.un {
  order:-2
}
.deux, .trois {
  order: 1;
}
.cinq {
  order:-1
}
<div class="conteneur">
  <div class="un">1</div>
  <div class="deux">2</div>
  <div class="trois">3</div>
  <div class="quatre">4</div>
  <div class="cinq">5</div>
</div>
Exemple d'ordonnancement des éléments

Interlude - Conception d’interface

~ petite musique d’ascenseur ~

Et la conception d’interface dans tout ça…

Conception d'interface Conception d'interface Conception d'interface Conception d'interface Conception d'interface Conception d'interface Conception d'interface Conception d'interface

Taille des éléments

Position et taille initiales des éléments

taille initiale

La taille initiale des éléments est gérée par la propriété flex-basis :

flex-basis: number | auto;

Si la taille du conteneur est plus grande :

taille initiale

Si la taille du conteneur est trop petite :

taille initiale taille initiale taille initiale taille initiale taille initiale

flex-shrink

flex-shrink permet de modifier la quantité de réduction à appliquer à un élément (1 par défaut) :

taille initiale taille initiale taille initiale taille initiale taille initiale taille initiale taille initiale
.deux {
  flex-shrink: 0
}
.un, .deux {
  flex-shrink: 0
}
.un {
  flex-shrink: 3
}
.deux {
  flex-shrink: 2
}

flex-grow

flex-shrink permet de modifier la quantité de réduction à appliquer à un élément (0 par défaut) :

taille initiale taille initiale taille initiale taille initiale taille initiale
.deux {
  flex-grow: 1
}
.deux {
  flex-grow: 1
}
.trois {
  flex-grow: 3
}

flex

flex est un raccourci pour flex-grow, flex-shrink et flex-basis :

flex: 0 1 auto;
flex: 1;
flex: 1 1 0;

Taille du body

Par défaut body et html ont leur hauteur définie pour l’affichage du contenu :

html, body {
  height: 100%;
}

De plus, body comporte par défaut des marges qui produisent l’apparition d’une barre de défilement :

html, body {
  height: 100%;
  margin: 0;
}

Les « media queries »

Concept

Permet l’ajout conditionnel de règles CSS en fonction :

  • d’un type de média,
  • de caractéristiques du média
  • pouvant être combinés avec des opérateurs logiques.

Type de média

Précise le type de périphérique, on dispose maintenant de all (défaut), print et screen.

@media print {
  ...
}
@media print, screen {
  ...
}
@media all {
  ...
}

Caractéristiques

Précise une caractéristique :

  • aspect-ratio
  • max-width
  • min-width
  • orientation
  • prefers-color-scheme
  • resolution
@media screen and (max-width: 600px) {
  body {
    background-color: lightblue;
  }
}
@media (max-width: 600px) {
  body {
    background-color: lightblue;
  }
}

Opérateurs logiques

Combinent plusieurs types ou caractéristiques :

  • and
  • ,
  • not
  • only
@media screen and (min-width: 600px) and (max-width: 800px),
       screen and (min-width: 1200px) {
  body {
    background-color: lightblue;
  }
}
@media ( screen and (min-width: 600px) and (max-width: 800px) ),
       ( screen and (min-width: 1200px) ) {
  body {
    background-color: lightblue;
  }
}
@media only screen and (min-width: 600px) {
  body {
    background-color: lightblue;
  }
}
@media not screen and (min-width: 600px) {
  body {
    background-color: lightblue;
  }
}

Interfaces

Modification structurelle de la page…

taille initiale taille initiale taille initiale taille initiale taille initiale

« Mobile-first »

.page__main, .content__main {
  display: flex;
  flex-direction: column;
}
.page__main, .content__main {
  display: flex;
  flex-direction: column;
}
@media (min-width: 600px) and (max-width: 800px) {
  .page__main {
    flex-direction: row;
  }
}
.page__main, .content__main {
  display: flex;
  flex-direction: column;
}
@media (min-width: 600px) and (max-width: 799px) {
  .page__main {
    flex-direction: row;
  }
}
@media (min-width: 800px) {
  .content__main {
    flex-direction: row-reverse;
  }
}

CSS et bonnes pratiques

Cascade

La cascade est un algorithme de filtre et de tri :

  • filtre sur le selecteur,
  • tri sur l’origine :
    • user-agent,
    • autheur,
    • utilisateur,
    • !important,
    • animation

Priorité des sélecteurs

Le CSS

div {
  background-color: red;
}
div {
  background-color: blue;
}
div.a {
  background-color: red;
}
div {
  background-color: blue;
}
div div {
  background-color: red;
}
div {
  background-color: blue;
}

Le HTML

<div>
  <div class="a">bleu</div>
  <div>bleu</div>
</div>
<div>
  <div class="a">red</div>
  <div>bleu</div>
</div>
<div>
  <div class="a">red</div>
  <div>red</div>
</div>

Spécificité

Sélecteursmillierscentainesdizainesunités
div.a11
div div.a12
#b .a11
Sélecteursmillierscentainesdizainesunités
div.a.b.c…261
#a1
  • milliers : attribut style (inline style),
  • centaines : identifiants CSS,
  • dizaines : classes CSS, pseudo-classes CSS ou attributs CSS,
  • unités : éléments CSS ou pseudo-éléments CSS.

Choix des sélecteurs

ul {
}
button {
}

Trop générique

#page {
}
#page ul.menu {
}
#page ul.menu {
}
#page ul.menu li.menu-item {
}
#page ul.menu li.menu-item button {
}

Complexe à maintenir

Bonnes pratiques :

  • minimiser la spécificité des sélecteurs,
  • encourager la réusabilité,
  • utiliser un nommage explicite.

Méthodologies

Avantages :

  • simple,
  • minimise la spécificité,
  • aide à la structuration et au nommage,
  • séparation structure / affichage.

Avantages :

  • minimise la spécificité,
  • réusabilité,
  • séparation structure / affichage,
  • séparation conteneur / contenant.

Avantages :

  • minimise la spécificité,
  • séparation structure / affichage,
  • séparation conteneur / contenant.

Avantages :

  • écosystème,
  • minimise la spécificité,
  • réusabilité.

Avantages :

  • minimise la spécificité,
  • réusabilité,

BEM

  • Block : une partie structurante mais indépendante de la page. (header, menu, input)
  • Element : une sous-partie, relative à un Block. (header title, menu item, input caption)
  • Modifier : un changement d’état ou de comportement d’un Block ou d’un Element. (disabled, highlighted, fixed, big size)

Convention de nommage

  • Block : .menu, .sub-header, .input.
  • Element : .menu__item, .sub-header__title, .input__caption.
  • Modifier : .menu--highlighted, .sub-header__title--small, .input__caption--error.

Bonnes pratiques

Pour renforcer la réutilisation d’un Block : on évite de les positionner (position, margin, float, …).

C’est le rôle du parent ou d’un Modificateur.

<header class=".header">
  <button class="header__connection button">
    Connection
  </button>
</header>
.header {
  position: relative;
  backgroud-color: #999;
}
.header__connection {
  position: absolute;
  top: 5px;
  right: 5px;
}
.button {
  border: 2px solid #78a;
}

Sélecteur

Modification CSS à l’aide de JavaScript.

Pour accéder à des éléments de la page HTML :

const element = document.querySelector(".menu");
const element = document.querySelector(".header .button.connection");
const elements = document.querySelectorAll(".menu");

Les événements en JavaScript

function clickHandle() {
  console.log("click");
}
const element = document.querySelector(".menu .toggle-display");
element.onClick = clickHandle;
function clickHandle() {
  console.log("click");
}
const element = document.querySelector(".menu .toggle-display");
element.addEventListener("click", clickHandle);
const element = document.querySelector(".menu .toggle-display");
element.onClick = function() {
  console.log("click");
}
const element = document.querySelector(".menu .toggle-display");
element.addEventListener("click",  function() {
  console.log("click");
});

onload

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title></title>
    <script src="js/scripts.js"></script>
    <link rel="icon" href="images/favicon.png" />
  </head>
  <body>
    ...
  </body>
</html>
window.addEventListener("load", function() {
  const element = document.querySelector(".menu .toggle-display");
})

classlist

    element = document.querySelector(".mon .selecteur");
    element.classlist.add("uneClasse");
    element.classlist.remove("uneClasse");
    element.classlist.toggle("uneClasse");
    element.classlist.contains("uneClasse");
    element.classlist.replace("uneClasse", "uneAutreClasse");
  • ajout d’une classe CSS,
  • suppression d’une classe CSS,
  • permutation de la présence d’une classe CSS,
  • test de la présence d’une classe CSS,
  • remplacement d’une classe CSS par une autre.
window.addEventListener("load", function() {
  const btnElt = document.querySelector(".menu .hide");
  btnElt.addEventListener("click",  function() {
    contentElt = document.querySelector(".main .content");
    contentElt.classlist.add("hide");
  });
}
window.addEventListener("load", function() {
  const btnElt = document.querySelector(".menu .show");
  btnElt.addEventListener("click",  function() {
    contentElt = document.querySelector(".main .content");
    contentElt.classlist.remove("hide");
  });
}
window.addEventListener("load", function() {
  const btnElt = document.querySelector(".menu .toggleDisplay");
  btnElt.addEventListener("click",  function() {
    contentElt = document.querySelector(".main .content");
    contentElt.classlist.toggle("hide");
    if (contentElt.classlist.contains("hide")) {
      btnElt.classlist.add("plus");
    }
    else {
      btnElt.classlist.remove("plus");
    }
  });
}

Pour poursuivre

Méthodologies :

Pré-processeurs :

Dpt Info A. Jonquet