8min.

Des panneaux dépliants flexibles en CSS

Section intitulée etat-des-lieuxÉtat des lieux

L’arrivée du module CSS Grid Layout (modèle de disposition en grille) et sa prise en charge par la majorité des navigateurs modernes a véritablement révolutionné notre façon de réaliser des mises en page, mais pas seulement…

Parallèlement, plusieurs astuces ont également vu le jour, dont une nous intéressant plus particulièrement aujourd’hui :

Simuler une transition CSS vers la valeur auto.

En effet, si vous utilisez le langage CSS régulièrement dans votre travail ou pour vos loisirs (chose que je comprendrais parfaitement 😏), vous avez sans doute été, un jour, confronté à ce problème : effectuer une transition ou une animation CSS entre les valeurs 0 et auto. Ces deux valeurs étant souvent associées à la propriété CSS height, afin d’afficher/masquer des panneaux dépliants tels que les accordéons.

En règle générale, une transition CSS entre deux états n’est possible que pour les propriétés CSS acceptant des valeurs numériques fixes (avec ou sans unité), des pourcentages, ou bien encore des couleurs.

La valeur auto représente un cas complexe et les spécifications requièrent de ne pas animer celle-ci. Il est donc, théoriquement, impossible d’effectuer une transition CSS vers la valeur auto.

Mais fort heureusement, il existe quelques astuces pour pallier cette limitation technique. 😉

Section intitulée la-technique-du-code-max-height-codeLa technique du max-height

Une des astuces les plus répandues est d’utiliser la technique du max-height.

Reprenons l’exemple évoqué précédemment, celui d’un panneau dépliant, en comparant la méthode classique basée sur la valeur auto associée à la propriété CSS height, et la technique basée sur la propriété CSS max-height.

Utilisation de la propriété CSS height avec la valeur auto :

.collapsible {
  height: 0;
  overflow: hidden;
  transition: height 0.4s;
}

.collapsible.is-expanded {
  height: auto;
}

Démonstration : Propriété CSS « height » et valeur « auto »

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac sapien augue. Integer rhoncus mauris id sodales semper. Suspendisse potenti. Aenean non orci vehicula nunc lacinia rutrum. Sed elit elit, ornare id metus sit amet, viverra rutrum mauris. Pellentesque gravida, lectus quis mattis auctor, nisi lacus cursus metus, a condimentum libero ex ac erat. Proin ultrices mauris ac arcu efficitur egestas. Fusce vel porttitor augue. Maecenas facilisis dolor aliquet, dapibus sapien sed, cursus purus. Nunc bibendum eros justo, sed mollis risus volutpat ac. Pellentesque non nulla purus. Pellentesque eu mauris ullamcorper felis pulvinar ornare non ut magna. Suspendisse sed nulla non ex mattis accumsan vitae vitae metus. Phasellus nec turpis magna.

Comme nous venons de l’expliquer, la transition CSS vers la valeur auto ne peut s’effectuer. 😢

Utilisons, cette fois-ci, la propriété CSS max-height avec une valeur définie explicitement :

.collapsible {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.4s;
}

.collapsible.is-expanded {
  max-height: 28rem;
}

Démonstration : Propriété CSS « max-height » et valeur définie explicitement

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac sapien augue. Integer rhoncus mauris id sodales semper. Suspendisse potenti. Aenean non orci vehicula nunc lacinia rutrum. Sed elit elit, ornare id metus sit amet, viverra rutrum mauris. Pellentesque gravida, lectus quis mattis auctor, nisi lacus cursus metus, a condimentum libero ex ac erat. Proin ultrices mauris ac arcu efficitur egestas. Fusce vel porttitor augue. Maecenas facilisis dolor aliquet, dapibus sapien sed, cursus purus. Nunc bibendum eros justo, sed mollis risus volutpat ac. Pellentesque non nulla purus. Pellentesque eu mauris ullamcorper felis pulvinar ornare non ut magna. Suspendisse sed nulla non ex mattis accumsan vitae vitae metus. Phasellus nec turpis magna.

Cette fois-ci, la transition CSS s’effectue correctement entre les valeurs 0 et 28rem, ces deux valeurs numériques étant définies explicitement.

Maintenant, cette technique est loin d’être parfaite puisqu’il est nécessaire de définir une hauteur maximale fixe.

En conséquence, si la hauteur intrinsèque du contenu à afficher est inférieure à la hauteur maximale déclarée (dans notre exemple 28rem), le contenu s’affichera correctement, dans le cas contraire, une partie du contenu sera rognée :

Démonstration : Propriété CSS « max-height » et valeur définie explicitement (contenu rogné)

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac sapien augue. Integer rhoncus mauris id sodales semper. Suspendisse potenti. Aenean non orci vehicula nunc lacinia rutrum. Sed elit elit, ornare id metus sit amet, viverra rutrum mauris. Pellentesque gravida, lectus quis mattis auctor, nisi lacus cursus metus, a condimentum libero ex ac erat. Proin ultrices mauris ac arcu efficitur egestas. Fusce vel porttitor augue. Maecenas facilisis dolor aliquet, dapibus sapien sed, cursus purus. Nunc bibendum eros justo, sed mollis risus volutpat ac. Pellentesque non nulla purus. Pellentesque eu mauris ullamcorper felis pulvinar ornare non ut magna. Suspendisse sed nulla non ex mattis accumsan vitae vitae metus. Phasellus nec turpis magna. Mauris a scelerisque orci. Pellentesque tristique, sem sit amet ultricies lobortis, risus est pulvinar neque, nec ullamcorper ante nunc ac arcu. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Fusce venenatis sodales libero id imperdiet. Donec rutrum cursus massa eget dictum. Vestibulum a augue nec velit volutpat vestibulum. Suspendisse eleifend nibh orci, nec faucibus dolor pharetra at. Aenean nec neque vitae diam efficitur eleifend et eu ex.

Oui… c’est tout de suite moins joli. 😕

Il existe bien évidemment d’autres solutions, mais généralement elles sont plus complexes à mettre en place et se basent sur du JavaScript afin de calculer et de définir explicitement la hauteur du panneau à déplier, via, notamment, la propriété scrollHeight.

Section intitulée css-grid-layout-a-la-rescousseCSS Grid Layout à la rescousse !

Heureusement, le module CSS Grid Layout et sa nouvelle unité de mesure, fr, nous apportent une solution beaucoup plus élégante et flexible, le tout, sans JavaScript.

L’unité fr représente tout simplement une fraction de l’espace disponible dans le conteneur de la grille. La valeur 1fr signifie que l’élément de la grille occupe l’intégralité de l’espace disponible.

L’exemple précédent peut, maintenant, se simplifier de cette façon :

.collapsible {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s;
}

.collapsible.is-expanded {
  grid-template-rows: 1fr;
}

.collapsible__inner {
  overflow: hidden;
}

Démonstration : CSS Grid Layout et unité « fr »

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac sapien augue. Integer rhoncus mauris id sodales semper. Suspendisse potenti. Aenean non orci vehicula nunc lacinia rutrum. Sed elit elit, ornare id metus sit amet, viverra rutrum mauris. Pellentesque gravida, lectus quis mattis auctor, nisi lacus cursus metus, a condimentum libero ex ac erat. Proin ultrices mauris ac arcu efficitur egestas. Fusce vel porttitor augue. Maecenas facilisis dolor aliquet, dapibus sapien sed, cursus purus. Nunc bibendum eros justo, sed mollis risus volutpat ac. Pellentesque non nulla purus. Pellentesque eu mauris ullamcorper felis pulvinar ornare non ut magna. Suspendisse sed nulla non ex mattis accumsan vitae vitae metus. Phasellus nec turpis magna.

Et oui, c’est tout ! 🎉

La transition CSS s’effectue correctement entre les valeurs 0fr et 1fr. Cette fois-ci, contrairement à la technique du max-height, le contenu s’affiche intégralement quelle que soit sa hauteur !

Section intitulée bonus-definir-un-nombre-donne-de-lignesBonus : Définir un nombre donné de lignes

Le module CSS Grid Layout, outre sa nouvelle unité de mesure, fr, nous apporte également une nouvelle fonction CSS : minmax().

La fonction CSS minmax() accepte deux paramètres… 🥁 min et max, définissant, ainsi, un intervalle. Si le paramètre max est inférieur au paramètre min, alors le paramètre max sera ignoré et sera considéré comme min.

Un cas d’utilisation est de rendre visible les premières lignes d’un article (potentiellement long), puis d’afficher un bouton permettant de révéler l’intégralité de celui-ci.

Utilisons cette fonction CSS afin de mettre à jour le code précédent :

.collapsible {
  display: grid;
  grid-template-rows: minmax(2.4rem, 0fr);
  transition: grid-template-rows 0.4s;
}

.collapsible.is-expanded {
  grid-template-rows: minmax(2.4rem, 1fr);
}

.collapsible__inner {
  overflow: hidden;
}

Améliorons ce code en définissant, via des propriétés personnalisées CSS (Custom Properties), le nombre exact de lignes à afficher par défaut (4 lignes dans l’exemple qui suit) :

:root {
  --font-size-base: 1.6rem;
  --line-height-base: 1.5;
  --baseline: calc(var(--font-size-base) * var(--line-height-base));
}

.collapsible {
  --collapsible-line-clamp: calc(4 * var(--baseline));

  display: grid;
  grid-template-rows: minmax(var(--collapsible-line-clamp), 0fr);
  transition: grid-template-rows 0.4s;
}

.collapsible.is-expanded {
  grid-template-rows: minmax(var(--collapsible-line-clamp), 1fr);
}

.collapsible__inner {
  overflow: hidden;
}

Démonstration : CSS Grid Layout et unité « fr » (nombre donné de lignes)

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac sapien augue. Integer rhoncus mauris id sodales semper. Suspendisse potenti. Aenean non orci vehicula nunc lacinia rutrum. Sed elit elit, ornare id metus sit amet, viverra rutrum mauris. Pellentesque gravida, lectus quis mattis auctor, nisi lacus cursus metus, a condimentum libero ex ac erat. Proin ultrices mauris ac arcu efficitur egestas. Fusce vel porttitor augue. Maecenas facilisis dolor aliquet, dapibus sapien sed, cursus purus. Nunc bibendum eros justo, sed mollis risus volutpat ac. Pellentesque non nulla purus. Pellentesque eu mauris ullamcorper felis pulvinar ornare non ut magna. Suspendisse sed nulla non ex mattis accumsan vitae vitae metus. Phasellus nec turpis magna. Mauris a scelerisque orci. Pellentesque tristique, sem sit amet ultricies lobortis, risus est pulvinar neque, nec ullamcorper ante nunc ac arcu. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Fusce venenatis sodales libero id imperdiet. Donec rutrum cursus massa eget dictum. Vestibulum a augue nec velit volutpat vestibulum. Suspendisse eleifend nibh orci, nec faucibus dolor pharetra at. Aenean nec neque vitae diam efficitur eleifend et eu ex.

Facile, non ? 😄

Section intitulée un-petit-mot-pour-la-finUn petit mot pour la fin

Aujourd’hui, de plus en plus de problématiques inhérentes à la conception d’interface riches peuvent être solutionnées, simplement, en quelques lignes de CSS.

Je pense, notamment, à la valeur smooth associée à la propriété CSS scroll-behavior permettant d’effectuer un défilement doux. Ou bien encore, la possibilité de créer une mise en page “masonry” en une seule ligne, grâce à cette simple déclaration : grid-template-rows: masonry.

Il y a quelques années, répondre à ces besoins n’était envisageable que par le biais de librairies JavaScript.

L’astuce CSS abordée dans cet article, fait, selon moi, partie de ces nombreuses évolutions techniques facilitant notre quotidien de développeur, tout en améliorant grandement l’expérience utilisateur. 👌

Commentaires et discussions

Nos formations sur ce sujet

Notre expertise est aussi disponible sous forme de formations professionnelles !

Voir toutes nos formations

Ces clients ont profité de notre expertise