[CSS]Panneau latéral coulissant

NoSmoking

Objectif

Faire apparaître/disparaître un panneau latéral coulissant à gauche de la fenêtre au clic sur une « languette » et ce sans JavaScript.

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">
  <div id="lateral-panel-bloc">
    <label id="lateral-panel-label" for="lateral-panel-input"></label>
    <div id="lateral-panel-content">
      <!-- ici le code HTML du panneau-->
    </div>
  </div>
</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>.

Application du CSS

CSS <div id="lateral-panel">

Commençons par positionner et dimensionner la <div id="lateral-panel"> qui est notre 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 par exemple.

Lors d'un translation du type transform:translateX(value), le pourcentage se réfère à la dimension de l'élément translaté.

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

Occupons nous maintenant 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 fenêtre.

#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 <div id="lateral-panel-bloc">

C'est cet élément que nous allons animer via l'action sur le <label>, donc cochage/décochage de l'<input id="lateral-panel-input">.

#lateral-panel-bloc {
  /*-- positions et dimensions --*/
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  /*-- visuel --*/
  border-right: 1px solid #CCC;
  background: #FFF;
  transition: transform .5s;    /* pour animation du panneau */
}

...

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 {
  /*-- positions et dimensions --*/
  z-index: 1;                   /* on le met au dessus */
  position: absolute;           /* pour sortir l'élément du flux, il va bouger */
  top: .5em;                    /* on décolle légèrement du haut */
  left: 100%;                   /* alignement sur le bord droit du parent */
  width: 3em;                   /* dimensions respectables */
  height: 5em;
  /*-- visuel --*/
  border: 1px solid #CCC;
  border-width: 1px 1px 1px 0;
  border-radius: 0 .5em .5em 0;
  font-size: inherit;
  background: #FFF;
  transition: all .5s;          /* pour animation éventuelle */
  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-content">

Il nous reste a définir l'élément « conteneur », la <div id="lateral-panel-content">.

#lateral-panel-content {
  padding: .5em;                /* on décolle le contenu du bord */
  overflow: auto;               /* rien ne doit déborder */
  max-height: 100%;             /* pas plus haut que son parent */
  box-sizing: border-box;       /* modèle de boîte, plus simple à gérer */
}

Les commentaires se suffisent à eux même.

Déplacement du panneau

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

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

Une seule règle suffit pour réaliser ce déplacement :

#lateral-panel-input:checked ~ #lateral-panel-bloc {
  transform: translateX(100%);  /* translation vers la droite de 100% */
}

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-bloc #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 cours à votre imagination pour une réalisation plus personnalisée.

Ressources

logo

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