Cours CSS / dimensions fluides avec min(), max-width et clamp()
Une disposition fluide permet aux dimensions de s'adapter à l'espace disponible tout en imposant des limites utiles. Les largeurs relatives, max-width, et des fonctions telles que clamp() peuvent maintenir le contenu lisible sans imposer les mêmes dimensions fixes sur chaque écran.
Séparer la largeur de la fenêtre d'affichage et la largeur disponible
La zone où une page web est affichée dans le navigateur est appelée la fenêtre d'affichage. Cependant, la largeur disponible pour les cartes dans le corps peut être inférieure à celle de la fenêtre d'affichage. Cela s'explique par le fait que la carte doit tenir dans l'espace restant en excluant la marge du parent, l'espacement avec les autres colonnes et la limite de largeur maximale.
Le pourcentage dans width: 100% utilise la largeur de la zone de base entourant l'élément dans une mise en page en bloc typique. 100vw est basé sur la largeur de la fenêtre d'affichage, donc même si vous le mettez à l'intérieur d'une petite carte, il peut être aussi grand que l'écran entier. Lorsque des barres de défilement verticales et des marges extérieures sont ajoutées, un débordement horizontal peut se produire. Pour la largeur des éléments à l'intérieur du corps, considérez d'abord le pourcentage ou la taille automatique.
| désignation | parents étroits | parents larges | Norme d'utilisation |
|---|---|---|---|
| width: 48rem | Peut être plus grand que les parents | Maintenir 48rem | Pas adapté comme valeur par défaut pour le texte pouvant être raccourci |
| width: 100% | Réduit pour correspondre aux parents | Continue d'augmenter jusqu'à la largeur du parent | Éléments qui doivent remplir le parent |
| width: 100%; max-width: 48rem | Réduit à moins de 48rem | Jusqu'à 48rem | Texte nécessitant une largeur de lecture limitée |
| min-width: 48rem | Ne réduit pas en dessous de 48rem | Décidé selon différentes règles de taille | À utiliser uniquement lorsqu'une taille minimale est requise |
Limiter et centrer la zone de contenu
*, *::before, *::after { box-sizing: border-box; }
.content {
width: 100%;
max-width: 48rem;
margin-inline: auto;
padding-inline: 1rem;
}
Avec border-box, les marges intérieures (padding) et les bordures s'ajustent à l'intérieur de la largeur déclarée. Si la police racine est de 16px et que le parent a une largeur de 390px, la largeur externe de cette boîte de contenu est de 390px et son padding de 16px de chaque côté laisse 358px pour le contenu. Avec une largeur de parent de 1000px, la largeur externe s'arrête à 768px et les marges automatiques la centrent. Pour plus de détails, voir Largeur, hauteur, limites min/max et box-sizing en CSS.
L'application de content-box au même élément ajoutera un padding à width: 100%, le rendant plus large que son parent. D'autre part, les marges ne sont pas non plus incluses dans le border-box. Lors de la spécification de width: 100% et de marges fixes des deux côtés ensemble, vous devez vérifier la somme totale. Si le min-width et le max-width sont en conflit, vérifiez également min-width, car le min-width peut le rendre plus grand.
Utilisez min() et clamp()
min() sélectionne la valeur la plus petite parmi les candidats. width: min(100%, 48rem) utilise la plus petite largeur entre la largeur du parent et 48rem, donc les limites de largeur de 100% et maximum spécifiées précédemment peuvent être exprimées en une seule déclaration.
.content { width: min(100%, 48rem); }
h1 { font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem); }
clamp(minimum, preferred, maximum) calcule la valeur préférée, puis la limite entre le minimum et le maximum. Dans le titre ci-dessus, rem est basé sur la taille de la police racine et vw est basé sur 1 % de la largeur de la fenêtre. Si la taille racine est de 16px, le minimum est 24px, le maximum est 40px et la valeur préférée est de 16px plus 2 % de la largeur de l'écran.
| largeur de la fenêtre | Valeur préférée calculée | taille réelle du titre |
|---|---|---|
| 320px | 16 + 6,4 = 22,4px | Minimum 24px |
| 600px | 16 + 12 = 28px | 28px |
| 1200px | 16 + 24 = 40px | 40px |
| 1600px | 16 + 32 = 48px | Maximum 40px |
Un texte dépendant uniquement de la largeur de la fenêtre peut devenir trop petit sur les écrans étroits ou lors d’un zoom. Pour les titres fluides, prévoyez une limite inférieure lisible et conservez une taille du corps de texte fondée sur rem. Mélanger rem et vw ne garantit pas à lui seul un agrandissement suffisant : la contribution de vw peut diminuer lorsque la fenêtre exprimée en pixels CSS devient plus étroite pendant le zoom. Vérifiez notamment le texte avec un zoom à 200% et avec une taille de police par défaut augmentée. La fourchette de cet exemple illustre le calcul et demande cette vérification avant utilisation sur un site. Consultez la documentation MDN sur clamp().
Exécutez l'exemple de carte fluide et d'image
Enregistrez le code suivant sous fluid-size.html en UTF-8 et ouvrez-le dans votre navigateur. L'image est un fichier de données SVG inclus dans le fichier, il n'est donc pas nécessaire de télécharger une image séparée ou une bibliothèque externe. Comparez la largeur du corps, le nombre de colonnes de cartes et la taille des titres sur un écran large et sur un écran étroit d'environ 390px. Si vous voulez placer plusieurs cartes de manière flexible, consultez CSS Grid : repeat, auto-fit, auto-fill et zones nommées pour savoir comment définir la largeur minimale des colonnes.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>fluid-size.html</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font: 1rem/1.6 sans-serif; color: #243447; }
h1, h2, p { margin-top: 0; } a { color: #145f8f; }
a:focus-visible, button:focus-visible, input:focus-visible { outline: 3px solid #ac4100; outline-offset: 3px; }
.content { width: min(100%, 48rem); margin-inline: auto; padding: 1rem; }
h1 { font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem); line-height: 1.3; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); gap: 1rem; }
.card { min-width: 0; padding: 1rem; background: #e8f3fa; overflow-wrap: anywhere; }
.card img { display: block; max-width: 100%; height: auto; margin-bottom: 1rem; }
.token { font-family: monospace; }
</style>
</head>
<body>
<main class="content">
<h1>Size elements to fit the screen and content</h1>
<p>The content is at most 48rem wide and shrinks to fit its parent on smaller screens.</p>
<div class="cards">
<article class="card"><img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22400%22%20height%3D%22300%22%20viewBox%3D%220%200%20400%20300%22%3E%3Crect%20width%3D%22400%22%20height%3D%22300%22%20fill%3D%22%23287699%22%2F%3E%3Crect%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%23205c32%22%2F%3E%3Crect%20y%3D%22265%22%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%239e3131%22%2F%3E%3Ccircle%20cx%3D%22200%22%20cy%3D%22150%22%20r%3D%2270%22%20fill%3D%22%23f6ae4c%22%2F%3E%3Crect%20x%3D%2212%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3Crect%20x%3D%22358%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3C%2Fsvg%3E" width="400" height="300" alt="Practice drawing with upper and lower bands and center circle"><h2>card with picture</h2><p>The image stays within the card width and preserves its original aspect ratio.</p></article>
<article class="card"><h2>A heading and description that wrap onto several lines</h2><p>Without a fixed height, the card grows as its text gets longer.</p></article>
<article class="card"><h2>Long identifier</h2><p class="token">ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</p></article>
</div></main>
</body>
</html>
La déclaration minmax(min(100%, 14rem), 1fr) fixe le minimum d’une colonne à la plus petite valeur entre 14rem et 100% de son conteneur. Une zone plus étroite que 14rem peut ainsi accueillir une colonne. auto-fit détermine combien de colonnes tiennent dans l’espace disponible et réduit à zéro les pistes répétées vides. Les pistes restantes se partagent l’espace avec 1fr. Le padding de chaque carte réduit la place disponible pour son texte et son image : raisonnez sur la largeur du conteneur, plutôt que sur le nom de l’appareil.
min-width: 0 supprime une contrainte de taille minimum qui pourrait empêcher la carte de rétrécir. overflow-wrap: anywhere fournit des coupures à l'intérieur d'une longue URL ou d'un identifiant si nécessaire. Ils ont des rôles différents : permettre à la boîte de rétrécir ne provoque pas par lui-même le retour à la ligne du texte. Le retour à la ligne change la présentation, pas la valeur de la chaîne copiée.
Tester un changement de taille à la fois
- Réduire l'écran à 390px. Le texte doit tenir dans l'écran, la carte doit être verticale, et les bandes au-dessus et en dessous de l'image ainsi que le cercle au centre doivent tous être visibles.
- Changer uniquement la largeur de
.contentà48rem. Après avoir vérifié pourquoi le texte dépasse sur l'écran étroit, le remettre àmin(100%, 48rem). - Changer uniquement la valeur maximale du titre à
3remet observer la différence sur un écran plus large. Calculez la valeur préférée pour comprendre pourquoi la taille reste identique sur les fenêtres étroites, puis rétablissez le maximum à 2.5rem. - Supprimez uniquement
overflow-wrap: anywherede.card. Observez si l’identifiant déborde de la carte, puis rétablissez la règle. Testez ensuite séparément la modification de la taille de police racine et le zoom du navigateur afin de ne pas mélanger les conditions.
Avant d'insérer overflow-x: hidden, qui cache le débordement, dans l'ensemble de la page, vérifiez la largeur, la marge, la largeur minimale et la chaîne. Si vous la cachez de la vue, le contenu ou les éléments de fonctionnement peuvent être coupés sans résoudre la cause. Pour les principes de base de la conception adaptative, vous pouvez également vous référer au guide de conception adaptative de MDN.




