aller au contenu principal

La fonction CSS clamp()

Le responsive fluide sans Media Queries


Publié le 23/01/2023 dans Blog
Crédit photo - Unsplash - Derek OyenCrédit photo : Unsplash - Derek Oyen
Je suis en train d'écrire un cours complet sur Flexbox. Il y aura un module entier sur la compréhension de ce mode de layout, et un module 100% pratique avec plus d'une dizaine d'exercices.Tu peux consulter le programme et à te préinscrire dès maintenant ! ⬇️Se préinscrire

Dans cet article nous allons nous intéresser à une fonction CSS que j'apprécie énormément : la fonction clamp().

Commençons par une définition : clamp() est une fonction CSS qui va te permettre d'écrêter une valeur entre deux bornes inférieure et supérieure.

La définition n'est peut-être pas claire pour toi pour le moment, donc prenons le temps d'étudier un cas concret pour que tu comprennes ce que la fonction va te permettre de faire.

Imaginons que tu souhaites avoir un titre responsive, tu veux qu'il soit petit sur les petites résolutions et grand sur les grandes résolutions.

Voyons ensemble, avant de voir comment la fonction clamp() peut nous aider, ce qu'il est possible de faire en CSS pour rendre du texte responsive.

Utiliser des Media Queries

Tu peux définir la taille d'un texte en pixel et la changer avec des Media Queries en fonction de la largeur du viewport, comme ceci ⤵️

h1 {
    font-size: 20px;
}
@media (width > 768px) {
  h1 {
    font-size: 36px;
  }
}
@media (width > 991px) {
  h1 {
    font-size: 54px;
  }
}

Un des problèmes de cette syntaxe est qu'il faut écrire pas mal de lignes pour arriver à avoir un titre responsive, et encore on pourrait vouloir cibler des résolutions encore plus grandes.

Par contre cette façon de procéder a un avantage : on garde le contrôle sur la taille du texte, le prix à payer est qu'il faut la définir de manière explicite, ici en pixel.

Bizarre cette syntaxe des Media Queries
Tu trouves peut-être la syntaxe que j'ai utilisé pour les Media Queries étrange ? Il s'agit d'une nouvelle syntaxe, j'en parle dans mon TIL (Today I Learned) de janvier 2023. 🙂

Utiliser les Viewports Units

On peut vouloir "perdre" un peu de contrôle et définir la taille de notre texte de façon dynamique.

Pour cela, on peut utiliser des Viewport Units pour avoir quelque chose de "fluide".

Les Viewport Units (vh, vw, vmin, vmax..), sont des unités CSS qui permettent d'avoir des valeurs dynamiques car elles sont basées sur la taille du viewport.

Pour faire simple : 90vw (vw = viewport width) correspond Ă  90% de la largeur du viewport.

Si on imagine un viewport de 1000px de large, alors 90vw vaut 900px.

Quelques mots de sur le fonctionnement du CSS
Les vw et les autres unités CSS dynamiques sont "résolues" par le navigateur lors du rendu de la page Web, cette étape s'appelle le "resolving", durant cette étape, les valeurs dynamiques comme 5vw sont converties en pixel par le navigateur.

On peut se servir des Viewport Units pour rendre du texte responsive de façon "fluide" comme ceci ⤵️

h1 {
  font-size: 5vw;
}

L'utilisation ici des Viewport Units présente un inconvénient, dans le cas d'un texte, ce dernier va être très petit sur mobile, et très gros sur les grandes résolutions.

C'est normal, il s'adapte à la largeur (si tu utilises vw) du viewport ⤵️

Un texte trop gros sur les grandes résolutions et trop petit sur les petites résolutions

Régler (ou presque) le problème

Alors il y a une solution mais qui ne règle pas complétement le problème, c'est de rajouter l'utilisation de la fonction calc() ⤵️

h1 {
  font-size: calc(16px + 5vw);
}

Le code ci-dessus permet d'avoir une taille de texte dynamique qui fera au minimum 16px + 5vw, donc cela règle le soucis du texte trop petit sur mobile, mais cela ne règle pas celui sur les grandes résolutions, on l'a même empiré car on rajoute 16px !

Le fait d'introduire une valeur fixe en pixel permet de garder le contrôle sur les petites résolutions, mais pas sur les grandes.

Le fonctionnement de clamp()

Si je te disais qu'il est possible avec clamp() de garder cette approche de design "fluide" mais en précisant en CSS, une valeur minimale et maximale qui ne peut pas être dépassée, ça serait cool non ? 🙂

La fonction clamp() prend 3 paramètres :

  • une valeur minimale
  • la valeur Ă  tester, aussi appelĂ©e "valeur prĂ©fĂ©rĂ©e"
  • et une valeur maximale.

Pour le premier et le dernier paramètre c'est simple, si on utilise clamp(20px, 5vw, 54px) sur un titre, ce dernier ne fera jamais moins de 20px, et jamais plus de 54px.

Intéressons nous au deuxième paramètre : 5vw, il faut voir cette valeur comme la taille de texte préférée, celle qu'on veut par défaut en quelque sorte.

Il faut te dire qu'elle est utilisée tout le temps, sauf si 5vw est inférieur à 20px, ou si 5vw est supérieur à 54px.

Pour rappel vw est dynamique, sa valeur change en fonction de la taille du viewport, donc si le viewport est petit, alors 5vw sera petit aussi, et inversement s'il est grand !

5vw peut être plus petit que 20px, ou plus grand que 54px (on l'a vu en début d'article), mais si cela arrive, alors cette valeur préférée ne sera pas utilisée !

Voici un graphique qui devrait t'aider à visualiser le fonctionnement de clamp() ⤵️

Le fonctionnement de la fonction CSS clamp()

Il est possible de faire des maths dans clamp(), en faisant par exemple un clamp(20px, 5vw + 16px, 70px) !

Tu seras peut-être plus à l'aise avec cette façon de coder, car mentalement tu sais ce que représente 16px, alors que 5vw c'est un peu plus difficile. Mais on a besoin de mettre une viewport unit, ou une unité CSS relative pour "dynamiser" la valeur préférée.

Avec clamp() il est alors possible de créer du texte responsive, sans Media Queries, juste avec une ligne de CSS, tout en gardant le contrôle sur la taille minimale et maximale qu'il doit avoir ⤵️

h1 {
  font-size: clamp(20px, 16px + 5vw, 54px);
}

Voila le résultat, tu peux voir que maintenant le texte est lisible sur toutes les résolutions :

Un texte avec une taille adaptée sur toutes les résolutions

Tu trouveras un CodePen avec un exemple d'utilisation sans et avec la fonction clamp(), n'hésite pas à modifier la largeur du viewport pour voir le texte grandir ou rétrécir.

Vers la fin des Media Queries ?

Il faut savoir que la fonction clamp() peut être utilisée aussi sur les margin et les padding, on pourrait donc se demander si l'utilisation des Media Queries est encore pertinente.

Pour rappel, le CSS à base de Media Queries, ce sont des changements de style qui interviennent sur des breakpoints bien précis.

Avec les Media Queries, le texte aura des tailles bien définies, qui changent selon la résolution. Les changements se font de façon "soudaine", puisque si on change la résolution ne serait-ce que d'un pixel, la mise en forme peut changer.

Voici un schéma pour visualiser la différence entre une approche avec des Media Queries et une approche "fluide" ⤵️

Une comparaison entre les Media Queries et une approche fluide avec la fonction clamp()

On pourrait se dire qu'une approche "fluide" avec clamp() est mieux car plus rapide Ă  Ă©crire et plus moderne.

Je ne dirais pas qu'elle est mieux mais différente, elle vient résoudre un problème à sa façon, ce qui est sûr, c'est quelle est plus concise.

Si on veut avoir un contrôle total sur la taille d'un texte, on peut garder l'utilisation des Media Queries. C'est quelque chose qui peut être voulu, un Webdesigner peut dessiner un texte qui aurait une taille bien précise sur différentes résolutions, et ne pas vouloir que la taille varie en fonction de la largeur ou hauteur du viewport.

Pour finir sache qu'on ne peut pas utiliser clamp() partout, par exemple on ne peut pas s'en servir sur une couleur ! La fonction peut être uniquement utilisée avec certains types comme <length>, <number> ou encore <percentage>..

Si cet article t'as plu, tu peux le partager pour m'aider à donner plus de visibilité à mon travail. 🥰

Tu peux aussi t'inscrire à ma newsletters via le formulaire juste en-dessous pour recevoir mes emails et être prévenu de la sortie des prochains articles !

Seb.

D'autres articles qui peuvent t'intérésser :

2023 SĂ©bastien Imbert