Choisir comment positionner un élément en CSS est parfois vraiment un choix sur les effets secondaires les plus acceptables.
Positionner des mises en page en CSS était autrefois une tâche très intimidante, et des hacks comme l’utilisation de tableaux pour l’ensemble de la mise en page étaient assez courants. Au fil des ans, la demande de meilleurs outils de mise en page a conduit à un support et des techniques de plus en plus performants.
Aujourd’hui, nous avons des options, et apprendre à gérer chacune de ces techniques est la clé pour créer des mises en page complexes qui restent faciles à modifier et suffisamment flexibles pour gérer plusieurs tailles d’écran.
- Grid
- Flexbox
- Position
- Floats
Grid
Grid est la plus récente façon de créer des mises en page sur le web. C’est un ensemble puissant de règles qui vous permettent de positionner des éléments sur un plan vertical et horizontal.
Contrairement à flexbox, la grille doit être utilisée pour une mise en page plus importante. Flexbox peut, et devrait, être placé à l’intérieur d’une mise en page de grille pour aider à positionner les composants qu’une mise en page de grille contient. La prise en charge de grid par les navigateurs est excellente, à l’exception de quelques problèmes avec Internet Explorer qui nécessitent un préfixe fournisseur pour gérer une version antérieure de la spécification.
Il y a beaucoup de propriétés et de fonctions à apprendre pour mettre en œuvre la grille, mais une fois mise en place, elle fait des merveilles pour garder vos mises en page flexibles et maintenables.
Voici comment commencer avec une disposition en grille sur votre page :
<body> <header></header> <nav></nav> <main></main> <footer></footer> </body>
body { display: grid; }
C’est tout ! Vous ne verrez pas encore de changements visuels avec cette configuration car, contrairement à flexbox, la direction de mise en page par défaut est par rangée (ce qui signifie que les éléments sont empilés verticalement les uns sur les autres). Mais vous avez franchi une étape importante dans la configuration de votre nouvelle disposition en grille : tous les éléments enfants de premier niveau de body
sont désormais des éléments de grille ! Vous pouvez maintenant contrôler leur position, leur alignement et leur largeur avec quelques déclarations supplémentaires.
Modèles de colonne et de rangée
grid-template-rows
et grid-template-columns
sont des propriétés qui définissent explicitement le dimensionnement de la voie des éléments de la grille horizontalement (colonne) ou verticalement (rangée). Vous pouvez définir une seule direction ou les deux ! Vous pouvez définir la taille de chaque élément de la grille avec une variété d’unités de mesure. L’ordre des valeurs dans la grille est appliqué respectivement à l’ordre des éléments dans le DOM au sein du conteneur de la grille (par exemple, dans l’exemple ci-dessous, si le premier élément du corps est l’en-tête, il obtiendra une hauteur de rangée de 100px)
body { display: grid; grid-template-rows: 100px 5rem auto 30%; }
Vous pouvez créer des colonnes et des lignes de grille implicites avec grid-auto-rows
et grid-auto-columns
qui ne nécessitent qu’une seule valeur de mesure qui s’appliquera à tous les éléments enfants directs de la grille.
body { display: grid; grid-auto-rows: 30px; }
Flux automatique
grid-auto-flow
contrôle la façon dont les éléments sont automatiquement placés dans la grille. Cette propriété ressemble beaucoup à flex-direction
car elle dirige l’empilement automatique des éléments, verticalement ou horizontalement. La valeur par défaut est row
, mais une valeur de column
peut être utilisée pour que les éléments soient placés les uns à côté des autres le long de l’axe horizontal. Vous pouvez utiliser grid-auto-flow
sans définir les tailles des lignes/colonnes du modèle si vous cherchez simplement à modifier le sens de l’empilement.
body { display: grid; grid-auto-flow: column; }
En outre, vous pouvez définir une valeur de dense
qui vise à « remplir les trous » dès que possible dans la grille. Vous pouvez également préciser la direction de la densité avec column dense
ou row dense
. La mise en garde à l’utilisation de cette valeur est qu’elle peut placer un élément hors de l’ordre dans votre grille pour tenter d’occuper tout espace vide inutilisé.
body { display: grid; grid-auto-flow: row dense; }
L’unité fractionnaire
Grid introduit également une nouvelle unité appelée fraction ou fr
fr
définit la proportion que doit prendre un élément par rapport à son contenant (pensez au mélange de cocktails : 7 parts de gin et 1 part de vermouth sec pour faire un martini). Dans l’exemple ci-dessous, les deux premiers éléments de la grille occuperont des proportions égales, tandis que le troisième élément occupera trois fois la taille des deux premiers ; le dernier élément aura la même taille que les deux premiers.
body { display: grid; grid-template-rows: 1fr 1fr 3fr 1fr; }
Zones de modèle de grille
grid-template-areas
attribue des noms aux cellules de la grille qui peuvent être référencés dans les éléments enfants pour les placer sur la grille. Ce qui est cool avec les zones de grille, c’est que vous dessinez en quelque sorte votre grille à l’aide d’une déclaration (cela permet également de réaliser des media queries étonnamment simples). Chaque chaîne distincte (dans chaque bloc de guillemets) représente une ligne distincte ; chaque élément de cette chaîne représente une colonne distincte. Vous pouvez répartir un élément sur plusieurs colonnes ou lignes en répétant le nom (les cellules doivent avoir une forme rectangulaire ; vous ne pouvez pas les disjoindre). Cette méthode de dénomination des zones de grille est pratique lorsqu’il s’agit d’une mise en page de haut niveau pour une meilleure lisibilité dans un édredon complexe d’éléments.
body { display: grid; grid-template-areas: "head head" "nav main" "foot foot"; }
Les zones de modèle définies ci-dessus doivent correspondre à des éléments particuliers en utilisant la propriété grid-area
.
header { grid-area: head; } nav { grid-area: nav; } main { grid-area: main; } footer { grid-area: foot; }
L’ajout d’un point dans une chaîne de rangée indique au navigateur de rendre une cellule vide.
body { display: grid; grid-template-areas: "head ." "nav main" "nav foot"; }
Les éléments de la grille peuvent être organisés dans n’importe quel ordre. Mais méfiez-vous des problèmes d’accessibilité liés à la réorganisation totale des éléments DOM, car cela peut être une expérience frustrante avec les lecteurs d’écran et la tabulation.
body { display: grid; grid-template-areas: "foot . ." "main nav nav" "head head head"; }
La fonction de répétition
Si vous souhaitez créer un modèle de mesure pour vos éléments de grille (sans écrire la même valeur encore et encore), vous pouvez utiliser la fonction de répétition. Cette fonction prend deux arguments : le nombre de répétitions et la largeur/hauteur de chaque colonne ou ligne. Dans l’exemple ci-dessous, chaque ligne de la grille occupera une hauteur égale sur 3 colonnes. Cela définira également l’enveloppement des éléments dans votre grille.
body { display: grid; grid-template-columns: repeat(4, 1fr); }
Un motif de répétition peut également prendre plusieurs valeurs de mesure pour définir un motif plus complexe.
body { display: grid; grid-template-columns: repeat(2, 100px 1fr); }
Il est également important de noter que la grille a également introduit d’autres fonctions utiles telles que minmax et fit-content.
Espace de la grille
Peut-être que la propriété la plus excitante maintenant à notre disposition est grid-gap
, qui définit les gouttières ou les espaces entre les lignes et les colonnes. Avant l’existence de cette fonctionnalité pratique, la définition des gouttières était une tâche ardue nécessitant des marges négatives et des calculs de largeur précis.
grid-gap
est un raccourci pour row-gap
et column-gap
et prend la plupart des valeurs de mesure. L’écriture d’une seule valeur applique le même écart aux lignes et aux colonnes ; l’écriture de 2 valeurs distinctes l’une à côté de l’autre applique chaque écart aux lignes et aux colonnes respectivement. Si vous souhaitez uniquement spécifier un écart aux colonnes ou aux lignes, utilisez row-gap
ou column-gap
avec une seule valeur.
body { display: grid; grid-auto-rows: 30px; grid-gap: 2rem; }
Colonne et ligne de la grille
Tout le positionnement de la grille ne doit pas se faire dans l’élément parent ; les éléments enfants prennent quelques propriétés pour un meilleur contrôle. grid-area
est utilisée pour définir la position d’un élément lors de l’utilisation de grid-template-area
(détaillée dans une section précédente). Si votre grille est dessinée avec des lignes/colonnes modèles ou automatiques, vous pouvez positionner précisément les éléments sur des lignes de grille spécifiques. Pour ce faire, vous pouvez utiliser les propriétés grid-column
et/ou grid-row
. Il s’agit d’abréviations pour grid--start
et grid--end
, séparées par une barre oblique (par exemple grid-column: grid-column-start / grid-column-end
).
Il est important de noter que les lignes de la grille commencent et se terminent sur le conteneur extérieur et sont numérotées en commençant par 1. Par exemple, une grille avec 6 colonnes aura 7 lignes de grille.
body { display: grid; grid-template-columns: repeat(6, 1fr); } header { grid-column: 2 / 4; }
Nous pouvons également indiquer à un élément de grille de se répartir sur un certain nombre de colonnes ou de lignes avec span
.grid { display: grid; grid-template-columns: repeat(6, 1fr); } header { grid-column: span 3; }
Auto-alignement
Dans la section flexbox, nous aborderons l’alignement des parents avec align-content
justify-content
align-items
et justify-items
(qui s’appliquent également à la grille). Maintenant, nous pouvons appliquer certaines propriétés similaires aux éléments enfants eux-mêmes avec align-self
et justify-self
. Les deux prennent des valeurs de chaîne de caractères telles que center
start
et end
Align-self
s’aligne sur l’axe du bloc, tandis que justify-self
s’aligne sur l’axe de la ligne. L’alignement prend la quantité d’espace que le contenu à l’intérieur de l’élément de la grille prend et le place en conséquence.
body { display: grid; height: 100vh; } footer { align-self: end; }
Si vous voulez simplifier encore plus, vous pouvez utiliser la propriété raccourcie place-self, qui définit respectivement align-self
et justify-self
. Vous pouvez utiliser deux valeurs pour placer un élément, ou une valeur qui s’applique aux deux propriétés. Cela rend le centrage un jeu d’enfant.
body { display: grid; height: 100vh; } main { place-self: center; }
Le passé et l’avenir de la grille
La grille est peut-être l’une des techniques de mise en page les plus puissantes dont nous disposons actuellement sur le Web et a également été l’une des adoptions les plus rapides d’une spécification par les principaux navigateurs. Si vous utilisez encore IE, notez toutefois que vous pouvez toujours utiliser la grille avec un peu d’autoréfixation. Edge, en revanche, prend entièrement en charge la grille sans le besoin de préfixation.
Pour ce qui est de l’avenir, nous mettrons probablement à jour ce post pour inclure une fonctionnalité appelée subgrid, qui nous permettra d’imbriquer facilement les grilles !
Flexbox
Une bonne façon de gérer les éléments de tailles variables est d’utiliser les nouvelles propriétés flexbox introduites dans CSS3.1. Cela nous donne beaucoup plus d’options pour controllayout et a résolu certains des problèmes de longue date en CSS. La prise en charge des navigateurs est bonne, et avec un polyfill ou un fallback pour mettre Internet Explorer à niveau, c’est prêt pour une utilisation en production.
J’ai dit que nous n’allions pas parler du fonctionnement de CSS, mais flexbox est encore nouveau et malheureusement la syntaxe est très confuse. Flexbox est un outil si puissant et remplace tant d’autres solutions bricolées, que cela vaut la peine de prendre le temps de comprendre comment l’utiliser.
Sautons dans le vif du sujet. Voici comment configurer un élément pour utiliser flexbox.
<div class="container"> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div>
.container { display: flex; flex-direction: row; }
Définir le conteneur à display: flex
permet simplement au navigateur de savoir que nousindiquons aux enfants d’utiliser flexbox pour leur disposition. Ensuite, nous ajoutonsflex-direction: row
aux enfants pour les aligner horizontalement, et par défaut, ils auront la même largeur, sauf s’ils ont une largeur définie.
Flex-direction
Flex-direction vous permet de spécifier si vos éléments doivent être disposés verticalement ou horizontalement. Par défaut, la valeur sera row
, ce qui vous permet simplement de disposer les éléments horizontalement. Vous pouvez également utiliser column
pour passer à l’orientation moyenne.
.container { display: flex; flex-direction: row; }
N’oubliez pas que l’utilisation de column
peut affecter la façon dont les autres propriétés flexbox s’affichent sur vos éléments, et pour simplifier, nous parlerons surtout des éléments horizontaux car c’est de loin le cas d’utilisation le plus courant, mais gardez à l’esprit que cette autre option de direction existe.
Flex-wrap
Flex-wrap définit si les éléments doivent être forcés à tenir sur une seule ligne(no-wrap
, le comportement par défaut) ou autorisés à maintenir leur taille normale avecwrap
. La plupart du temps, vous voudrez le comportement par défaut, mais le fait de surcharger cette propriété vous permettra d’utiliser les autres propriétés de flexbox sans affecter les largeurs.
.container { display: flex; flex-wrap: wrap; }
Lorsqu’elle est définie sur no-wrap
, les éléments auront toujours une taille proportionnelle les uns aux autres.Par exemple, imaginez que les éléments d’une liste sont définis pour être 100px
larges, sauf le dernier qui est 200px
. Les éléments seront redimensionnés pour s’adapter au conteneur, mais le dernier élément sera toujours deux fois plus large que les autres.
Justify-content
Justify-content détermine comment espacer votre contenu dans votre ligne ou votre colonne.La valeur par défaut est flex-start
, ce qui alignera vos éléments à gauche. Naturellement,nous avons aussi flex-end
pour aligner les éléments à droite et center
pour les centrer.Les choses deviennent plus intéressantes avec space-between
, qui donnent un espacement égal entre les éléments mais pas aux extrémités, tandis que space-around
donne un espacement égal aux extrémités également.
.container { display: flex; justify-content: center; }
Ceci est mieux utilisé lorsque les éléments ont des largeurs définies (ou ont atteint leur maximumwidth).
Cela peut être vraiment utile pour aligner vos éléments flexbox sur votre grille, sans dépendre de choses comme les flotteurs.
Align-content
Align-content est similaire à justify-content
, mais contrôle où les éléments se trouvent sur l’axe transversal. Je dis « autre » car lorsque vous utilisezflex-direction: row
, alors align-items
contrôle l’alignement vertical, mais lorsque vous utilisez flex-direction: column
, c’est l’inverse.
Vous pouvez aligner les éléments sur la ligne de base du texte de chaque élément en utilisantbaseline
. Il existe également une option pour que chaque élément s’étende d’une extrémité de l’axe à l’autre avec stretch
.
.container { display: flex; align-items: center; }
Nous pouvons utiliser align-items: stretch
pour résoudre le problème des « colonnes de hauteur égale » qui plombe les mises en page CSS depuis le début. Vous pouvez également définir à la foisjustify-content
et align-items
center
pour centrer vos éléments au milieu de votre conteneur, ce qui est vraiment utile pour des choses comme les zones de héros et les pages splash.
Il y a plusieurs autres propriétés qui sont utilisées moins souvent mais que vous pourriez trouver utiles.
Align-items
Align-items affecte les lignes de contenu et l’endroit où elles doivent être dans leurconteneur. Vous pouvez voir ci-dessous que les éléments de chaque ligne conservent leur hauteur normale (sauf si vous utilisez stretch
).
.container { display: flex; align-content: stretch; }
Un peu plus de propriétés
Il existe également un certain nombre de propriétés flexbox pour les éléments du conteneur.Celles-ci sont un peu plus faciles à comprendre que les propriétés parentales et, heureusement, il existe un raccourci utile que nous pouvons utiliser pour faciliter les choses.
.list-item { flex: <flex-grow> <flex-shrink> <flex-basis>; }
-
flex-grow: <integer>
: Cela fournit un autre moyen de donner à vos éléments flexdifférentes largeurs. Si vous définissez tous vos éléments enfants àflex-grow: 1
, mais que vous définissez le dernier enfant àflex-grow: 2
, il sera deux fois plus large que ses frères et sœurs. -
flex-shrink: <number>
: Détermine comment l’élément se rétrécira lorsque leconteneur n’est pas assez large pour que les éléments conservent leur largeur naturelle. Si le dernier élément est défini surflex-shrink: 2
alors que ses frères et sœurs sont définis surflex-shrink: 1
, il rétrécira deux fois plus que ses frères et sœurs. -
flex-basis: <size>
: Ce que nous devons considérer comme étant la taille naturelle de l’élément. Cela peut être considéré comme le « point de rupture » auquel les propriétés grow et shrink sont déclenchées.
Order contrôle l’ordre dans lequel l’élément apparaît dans le conteneur. Les nombres négatifs sont acceptés et apparaîtront avant ce qui serait normalement le premier élément.
Align-self a toutes les mêmes options que align-items
, mais vous permet de contrôler comment les éléments individuels sont alignés. Par exemple, les frères et sœurs peuvent être réglés surflex-start
, mais vous pouvez choisir un élément à régler sur flex-end
.
Vous n’utiliserez probablement pas tous ces éléments ensemble, mais une telle monstruosité ressemblerait à ceci :
.container { align-items: flex-start; display: flex; height: 40em; } .item { flex: 1 1 2em; } .item:nth-child(3) { align-self: flex-end; flex: 2 10 5em; order: -1; }
Ressources d’apprentissage
Flexbox peut être une chose difficile à comprendre, surtout si vous êtes habitué aux bizarreries des mises en page CSS traditionnelles. Site comme Codepen sont une bonne façon d’apprendre est juste d’expérimenter et de voir ce que vous pouvez arriver.
Si vous n’êtes pas sûr de la façon dont vous utiliseriez flexbox dans une application du monde réel,Solved by Flexbox est une grande ressource mise en place par Mozilla qui présente beaucoup de grandes idées pratiques.
Position
Positionnement nous donne une méthode de mise en page complètement différente. La valeur par défaut est static
, et fait que l’élément se comporte normalement.
Utiliser position: relative
vous permet de spécifier un décalage avec top
bottom
left
, et right
.
.logo { position: relative; left: 1em; top: 1em; }
Cela peut être utile pour faire un simple décalage sans utiliser quelque chose comme margin
,mais cela devient vraiment puissant lorsqu’on contient un enfant avec position:absolute
.
Position absolue
Le positionnement absolu base la position des éléments par rapport à l’élément parent le plus proche qui a position: relative
défini. S’il n’en trouve pas, il sera relatif au document.
.hero { position: relative; } .hero-icon { position: absolute; left: 20px; top: 10%; }
Le positionnement absolu ne doit pas être utilisé pour mettre en page des colonnes de contenu. Parce que les éléments sont retirés du flux de document, cela signifie que chaque fois que vous ajoutez du contenu à une section, vous pouvez avoir à ajuster les tailles des autres sections à la main, et cela rend la conception réactive beaucoup plus de tracas que nécessaire.Réservez le positionnement absolu pour obtenir ces petits éléments de conception exactement où vous voulez qu’ils soient. En règle générale, si un élément peut être simplement positionné à l’aide de flotteurs ou d’une modification des styles display
, il est probablement préférable d’éviter le positionnement absolu.
Centrage à l’aide de la position absolue
Un élément qui peut être très utile mais qui fait trébucher beaucoup de débutants est le centrage des éléments à l’aide du positionnement absolu. Si votre élément a une taille définie, il s’agit simplement de le décaler en utilisant les marges. Reprenons le dernier exemple, mais centrons l’icône à la fois horizontalement et verticalement. Pour centrer un élément en utilisant le positionnement absolu, il suffit de suivre les étapes suivantes :
- Ajouter
left: 50%
à l’élément que vous souhaitez centrer. Vous remarquerez que cela aligne le bord gauche de l’élément enfant avec la ligne des 50 % du parent. - Ajoutez une marge gauche négative égale à la moitié de la largeur de l’élément.Cela nous ramène sur la moitié du chemin.
- Puis, nous allons faire un processus similaire pour l’axe vertical. Ajoutez
top: 50%
à l’enfant - Et puis ajoutez une marge supérieure négative égale à la moitié de sa hauteur.
Cela signifie que même si le conteneur peut changer de taille, l’élément centré restera exactement là où nous le voulons. Le CSS résultant devrait ressembler à quelque chose comme ceci:
.container { position: relative; } .centered-element { height: 100px; width: 100px; position: absolute; left: 50%; margin-left: -50px; top: 50%; margin-top: -50px; }
Position fixe
Le positionnement fixe fonctionne comme absolute
, mais il est toujours relatif auviewport plutôt qu’au document et restera en place lorsque les utilisateurscrolls. Cela peut donner à votre application l’aspect d’une application native, avec un en-tête fixe ou une navigation latérale, ou pour tout élément que vous souhaitez garder à portée de main. Comme le positionnement absolu, les éléments fixes seront retirés du flux du document, vous devrez donc peut-être ajouter du padding sur un élément situé sous eux pour vous assurer que votre autre contenu sera toujours visible.
Position collante
Le positionnement collant est le plus récent du groupe. Il existe d’excellentsarticles sur la manière de l’utiliser, ainsi que des alternatives javascript.Il ne faut pas le confondre avec la technique toujours populaire du sticky footer,qui mérite également une mention spéciale.
Z-index
La propriété position nous donne l’avantage de pouvoir spécifier lez-index de nos éléments. Si nous revenons à notre métaphore de voir les éléments comme des morceaux de papier, la définition de la propriété z-index
nous permet de spécifier si notre papier se trouve au-dessus ou au-dessous des autres morceaux. Un nombre plus élevé apparaîtra au-dessus, et un nombre plus élevé apparaîtra en dessous. Vous pouvez également utiliser un nombre négatif, ce qui peut faire apparaître l’élément derrière le parent (ou même derrière le document tout entier) ! Cela peut conduire à une sorte de course aux armements avec des nombres de plus en plus élevés pour s’assurer qu’un élément se trouve toujours au sommet. Cela peut devenir assez ingérable et il est préférable d’utiliser le positionnement et les z-index de manière conservatrice.
Flots
Les flots sont la technique de mise en page la plus couramment utilisée en CSS, mais ils peuvent être frustrants si vous ne savez pas comment ils affectent leurs éléments voisins. Lorsque vous donnez un style à un élément avec float: left
, les éléments suivants vont refluer.Le flux du document est juste l’ordre du contenu et la façon dont les éléments se disposent les uns autour des autres. Si l’élément flottant n’a pas de largeur définie, il se réduit à la largeur du contenu. Si l’élément suivant est plus étroit que l’espace restant, il se déplacera vers la droite. Gardez à l’esprit que les éléments définis sur display: block
devront recevoir une largeur définie ou ils resteront sur leur propre ligne.
Vous pouvez empêcher un élément de refluer en lui donnant une propriété clear
dans votre feuille de style. Les options comprennent clear: both
clear: left
(qui permettra toujours le reflux des éléments suivants avec float: right
), et clear: right
(qui fait le contraire). Vous pouvez également utiliser clear: none
pour remplacer le comportement par défaut.
Parce que les enfants flottants provoqueront l’effondrement de leurs éléments parents, vous serez tenté de créer de nouveaux éléments juste pour ajouter clear: both
etprévenir ce comportement. Bien que cela fonctionne, nous voulons garder notre balisage sémantique, donc cela devrait être fait juste en utilisant CSS si possible. En utilisant un::after
pseudo-élément, vous pouvez créer un clearfix:
.container::after { clear: both; content: ""; display: table; }
L’utilisation d’un préprocesseur comme Bourbon permet de l’ajouter facilement en tant que mixin Sass :
.container { @include clearfix; }
Les flottants fonctionnent mieux pour les grands conteneurs, mais peuvent ne pas fonctionner aussi bien pour les éléments de texte car il sera difficile de les aligner. Vous trouverez peut-être que l’utilisation de display:inline-block
est meilleure pour ces situations.