[CSS]Panneau latéral coulissant

NoSmoking

Objectif

L'objectif est de faire apparaître un panneau latéral en cliquant sur une « languette » située en haut à gauche de la fenêtre d'affichage.

Une fois de plus nous allons utiliser un élément <input type="checkbox">, associé à un élément <label>, pour gérer l'action au click, c'est un grand classique.

Le résultat que l'on veut obtenir est le suivant :

Mise en place structure HTML

Nous utiliserons la structure suivante :

<div id="lateral-panel">
  <input id="lateral-panel-input" type="checkbox">
  <label id="lateral-panel-label" for="lateral-panel-input"></label>
</div>

On sait qu'en utilisant le sélecteur d'adjacence « élargie » ~ (tilde) l'<input> ne pourra cibler qu'un frère successeur. Il nous faut donc mettre un élément conteneur successeur de l'<input>.

Nous pourrions également mettre l'<input> avant la <div id="lateral-panel"> mais il me semble préférable de conserver tous les éléments dans un même conteneur de référence.

On se retrouve donc avec la structure suivante :

<div id="lateral-panel">
  <input id="lateral-panel-input" type="checkbox">
  <label id="lateral-panel-label" for="lateral-panel-input"></label>
  <div id="lateral-panel-bloc">
  </div>
</div>

Application du CSS

CSS <div id="lateral-panel">

Nous allons commencer par positionner et dimensionner la <div id="lateral-panel"> qui est le bloc de référence.

#lateral-panel {
  z-index: 9999;                  /* pour être au dessus des autres éléments */
  position: fixed;                /* ne suit pas le scroll de la page et sert de réfèrent */
  top: 0;                         /* position en haut */
  left: 0;                        /* à gauche */
  width: 20em;                    /* valeur de largeur pour tout le contenu */
  min-height: 100vh;              /* occupe toute la hauteur du viewport */
  transform: translateX(-100%);   /* on déplace à gauche pour ne pas interférer avec le document */
}

Si vous avez besoin de modifier la largeur du bandeau il est juste nécessaire d'ajuster la ligne width:20em de cet élément.

La déclaration transform:translateX(-100%) permet de déplacer l'élément hors de la fenêtre afin qu'il n'interfère pas avec le document en ce qui concerne les événements liés à la souris.

CSS <input id="lateral-panel-input">

Occupons nous de l'<input id="lateral-panel-input">, c'est le contrôleur de l'action, nous le déplaçons pour qu'il ne soit pas visible dans la page.

#lateral-panel-input {
  position: absolute;           /* pour sortir l'élément du flux */
  left: -999em;                 /* position hors de la fenêtre */
}

C'est tout, rien de plus.

CSS <label id="lateral-panel-label">

Maintenant plaçons et dimensionnons l'élément <label id="lateral-panel-label"> qui est la liaison entre l'utilisateur et l'<input id="lateral-panel-input">.

#lateral-panel-label {
  z-index: 1;                   /* on le met au dessus */
  position: absolute;           /* pour sortir l'élément du flux, il va bouger */
  top: 0;                       /* position en haut */
  left: 100%;                   /* alignement sur le bord droit du parent */
  width: 3em;                   /* dimensions respectables */
  height: 3em;
  cursor: pointer;
}

Jusque là, si tout va bien, on ne voit apparaître, dans le coin supérieur gauche, que cet élément.

CSS <div id="lateral-panel-bloc">

Il nous reste quand même à positionner et dimensionner l'élément « conteneur », la <div id="lateral-panel-bloc">.

#lateral-panel-bloc {
  z-index: 0;                   /* mise au niveau zéro */
  position: absolute;           /* pour sortir l'élément du flux, il va bouger */
  top: 0;                       /* position en haut */  
  left: 0;                      /* alignement sur bord gauche du parent */
  box-sizing: border-box;       /* modèle de boîte, plus simple à gérer */
  width: 100%;                  /* largeur 100% de son parent */
  height: 100%;                 /* hauteur 100% de son parent */
  padding: 1em;                 /* on décolle le contenu du bord */
  overflow: auto;               /* rien ne doit déborder */
}

Les commentaires se suffisent à eux même.

Déplacement du panneau

Le CSS de base étant posé il nous faut positionner les éléments pour que ceux ci soient visibles lorsque l'on a cliqué sur le <label id="lateral-panel-label">.

Deux règles suffisent pour réaliser cela :

#lateral-panel-input:checked ~ #lateral-panel-label {
  left: 200%;                     /* décalage vers la droite, passe de 100% à 200% */
}   
#lateral-panel-input:checked ~ #lateral-panel-bloc {
  transform: translateX(100%);    /* translation vers la droite de 100% */
}

Lors d'un décalage avec un left:200%, le pourcentage se réfère à la dimension du parent alors qu'avec un transform: translateX(100%) le pourcentage se réfère à la dimension de l'élément.

Pour animer le déplacement nous allons simplement ajouter une propriété transition:all .5s au CSS, on aura ainsi une impression de glissement à l'ouverture comme à la fermeture.

Le CSS ci dessous prend en compte le regroupement des propriétés communes plutôt liées au visuel.

#lateral-panel-label,
#lateral-panel-bloc {
  font-size: inherit;             /* taille font du référent */
  background: #FFF;               /* il faut un fond opaque */
  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
  transition: all .5s;
}

Voilà votre panneau coulissant est opérationnel.

Personnalisation de la « languette »

L'élément <input id="lateral-panel-label">, la « languette », est un peu terne, un simple rectangle blanc, nous allons lui apporter un aspect un peu plus avenant.

Nous allons utiliser le pseudo-élément ::before pour lui donner une apparence de flèche.

#lateral-panel-label:before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  box-sizing: border-box;
  width: 1em;
  height: 1em;
  border: .5em solid currentColor;
  border-width: .5em .5em 0 0;
  color: #888;
  transition: all .5s;
  transform: translate(-50%, -50%) rotate(45deg);
}

Nous ajoutons un petit effet de rotation pendant le déplacement avec la règle CSS suivante :

#lateral-panel-input:checked ~ #lateral-panel-label:before {
  transform: translate(-50%, -50%) rotate(-135deg);
}

Voilà un effet simple sur base d'un élément carré dont seulement deux côtés sont visibles et sur lequel on applique une rotation lors du déplacement.

Vous pouvez laisser libre cour à votre imagination pour une réalisation plus personnalisée.

Ressources

logo

Ce panneau latéral peut contenir un menu par exemple...