Aller au contenu

CSS Positionnement

La propriété display#

Par défaut, chaque boite de type block est positionnée l’une à la suite de l’autre, à la ligne. Elles peuvent être dimensionnées et les marges s’appliquent, contrairement aux éléments type inline.

Il est possible de changer le comportement initial de chaque élément à l’aide de la propriété display.

  • display: block: convertit un élément en type block
  • display: inline: convertit un élément en type inline

L’utilisation d’un display: block sur un élément inline permet notamment de pouvoir lui affecter une taille, mais l’élément crée une nouvelle ligne.

Pour ce qui est de la création d’architecture globale, il existe 2 modes de positionnement en CSS : Grid et Flexbox

Grid#

Pour réaliser une architecture simplement, le mode Grid est préconisé. Pour cela :

  • display: grid pour définir un élément comme nouvelle grille

Sur cet élément, il faut alors définir les lignes et colonnes virtuelles :

  • grid-template-columns: 100px 1fr pour définir les colonnes. Ici, une première colonne de 100px, puis une seconde d’une fraction de l’espace restant (unité fr)
  • grid-template-rows: 100px auto 100px pour définir les lignes. Ici, une première et dernière ligne de 100px. La seconde ligne a une hauteur basée sur le contenu de l’élément enfant

Ensuite, il ne reste plus qu’à positionner les éléments au sein de cette grille :

  • grid-column: 1 positionne l’élément dans la colonne 1
  • grid-column: 1 / 3 positionne l’élément de la colonne 1 à la colonne 3 (exclue)
  • grid-column: 1 / span 2 positionne l’élément de la colonne 1, puis s’étend sur 2 colonnes (mot-clé span)
  • idem pour les lignes avec grid-row

Voilà un exemple de grille

Partie HTML

<body>
  <header></header>
  <nav></nav>
  <article></article>
  <footer></footer>
</body>

Partie CSS

body {
  min-height: 100vh;                  /* 1 */
  display: grid;                      /* 2 */
  grid-template-columns: 200px 1fr;   /* 3 */
  grid-template-rows: 50px 1fr 50px;  /* 3 */
}
header {
  grid-column: 1 / span 2;            /* 4 */
}
nav {
  grid-column: 1;                     /* 5 */
  grid-row: 2;                        /* 5 */
}
article {
  grid-column: 2;                     /* 6 */
}
footer {
  grid-column: 1 / span 2;            /* 7 */
  grid-row: 3;                        /* 7 */
}

On a donc :

  1. On définit une hauteur minimale de 100% de la hauteur de l’écran (unité vh)
  2. On définit le mode grid
  3. On crée 2 colonnes (200px et 1fr) et 3 lignes (50px, 1fr et 50px)
  4. Le <header> est positionné dans la première colonne, et s’étend sur 2 colonnes
  5. Le <nav> est positionné dans la première colonne de la seconde ligne (grid-row est facultatif car le <header> occupe toute la première ligne)
  6. Le <article> est positionné dans la seconde colonne
  7. Le <footer> est positionné dans la troisième ligne, et s’étend sur 2 colonnes

Notez qu’il est également possible d’imbriquer les niveaux de grille. Un enfant d’une grille peut définir une grille pour ses propres enfants.

Le mode Grid étant assez récent, il est préférable d’utiliser Autoprefixer pour ajouter les préfixes afin de supporter des navigateurs plus anciens

Jouez !

Manipulez CSS Grid avec ce jeu :

Exercice - Finalisez l’architecture des éléments#

  • Body:

    • Modification du mode d’affichage vers Grid
    • Création de 2 colonnes (240px et 1fr)
    • Création de 3 lignes (auto , 1fr et auto)
  • Entête

    • Occupe toute la première ligne
  • Menu

    • Occupe la première colonne de la deuxième ligne
  • Contenu

    • Occupe la deuxième colonne de la deuxième ligne
  • Menu et contenu

    • Gestion des marges internes, externes
    • Attention aux images qui débordent ou qui agrandissent la grille (utilisation de max-width)
  • Pied de page

    • Occupe toute la dernière ligne

Flexbox#

Pour réaliser des composants flexibles, il existe le modèle Flexbox. Pour cela :

  • display: flex pour définir un élément Flexbox

Sur cet élément, il faut alors définir ses axes que les enfants vont suivre

  • flex-direction définit l’axe principal (avec les valeurs column, column-reverse, row ou row-reverse). Défaut row, les enfants sont affichés les uns à coté des autres
  • l’axe secondaire est perpendiculaire à l’axe principal

Chaque enfant est donc flexible au sein de son parent. Sa taille est calculée en fonction de la taille déclarée en CSS et l’espace restant à ­remplir. La propriété flex gère cela et est un raccourci de 3 autres :

  • flex-grow: 1 définit le facteur d’étirement possible des éléments (s’il y a de l’espace libre)
  • flex-shrink: 1 définit le facteur de rétrécissement possible des éléments (s’il n’y a pas assez d’espace)
  • flex-basis: 50px définit la taille de base souhaitée

Par défaut, c’est flex: 0 1 auto. Un élément récupère donc sa taille définie avec width, il ne peut pas s’étirer, mais peut se rétrécir.

Voilà un exemple de composant flexible

Partie HTML

<ul id="menu">
  <li>...</li>
  <li>...</li>
  <li>...</li>
  <li>...</li>
</ul>

Partie CSS

ul {
  display: flex;        /* 1 */
  flex-direction: row;  /* 2 */
}
li {
  flex: 1 0 150px;       /* 3 */
}

On a donc :

  1. On définit le mode Flexbox
  2. On précise que les éléments s’affichent en ligne (par défaut)
  3. On précise que les éléments
    • ont une taille (largeur) souhaitée de 150px
    • peuvent s’agrandir si l’espace le permet (flex-grow: 1)
    • ne peuvent pas se réduire (flex-shrink: 0)

Notez également que chaque enfant peut à son tour être un élément Flexbox pour ses propres enfants.

Jouez !

Manipuler CSS Flexbox avec ce jeu :

Alignements Grid et Flexbox#

Propriétés#

Les propriétés d’alignements respectent le même modèle dans Grid et Flexbox. Elles commencent par :

  • justify-* pour les propriétés d’alignements selon l’axe principal (le sens de lecture par défaut)
  • align-* pour les propriétés d’alignements selon l’axe secondaire (de haut en bas par défaut)

Suivies de :

  • *-content pour aligner la grille (les lignes et les colonnes)
  • *-items pour aligner les éléments de cette grille
  • *-self pour aligner un élément indépendamment

Pour Grid, c’est donc un jeu de 6 propriétés :

  • justify-content / align-content pour aligner la grille (les colonnes et les lignes)
  • justify-items / align-items pour aligner le contenu de la grille (les éléments au sein de chaque cellule)
  • justify-self / align-self pour aligner un élément de la grille indépendamment

Pour Flexbox, c’est quasiment la même chose. Pour simplifier, on considère qu’un élément Flexbox est un élément Grid d’une seule ligne, ses colonnes étant définies par ses enfants. On a donc uniquement :

  • justify-content pour aligner la «grille» (et donc ses enfants) sur l’axe principal
  • align-items pour aligner le contenu de la «grille» (ses éléments de l’unique ligne) sur l’axe secondaire
  • align-self pour aligner un élément indépendamment

Dans Flexbox, on peut noter que :

  • align-content permet d’aligner plusieurs lignes d’un élément Flexbox (si forcé avec flex-wrap)
  • justify-items et justify-self n’existent pas en mode Flexbox. Les enfants sont considérés comme les colonnes et sont donc alignés avec justify-content

Valeurs#

Pour toutes ces propriétés justify-* et align-*, voici les valeurs utilisables :

  • start aligne au départ (flex-start pour Flexbox)
  • center aligne au centre
  • end aligne à la fin (flex-end pour Flexbox)

En plus pour les propriétés d’alignements des lignes et colonnes de la grille (*-content) :

  • space-around / space-between / space-evenly distribue l’espace

Et enfin, pour les propriétés d’alignements des éléments (*-items, *-self) :

  • stretch pour étirer

Les marges classiques continuent de fonctionner, et notamment margin: auto des 4 cotés. Pour des marges sur les lignes et colonnes au sein de Grid, il existe les propriétés gap, row-gap et column-gap.

Exercice - Flexbox#

  • Créez une nouvelle page HTML
  • Partez du code HTML ci-dessous (un menu de navigation, et un champ de recherche)
<nav>
    <ul>
        <li>Logo</li>
        <li>Home</li>
        <li>Products</li>
        <li>Services</li>
    </ul>
    <form>
        <input type="text">
        <button>Go</button>
    </form>
</nav>
  • Faites-en sorte d’obtenir le résultat visuel ci-dessous :
    • les éléments <ul> et <form> sont côte à côte, et alignés verticalement
    • la navigation (<ul>) est alignée à gauche
    • le <form> est aligné à droite
    • les éléments de listes (<li>) n’ont pas de puces et sont espacés

Rendu visuel attendu

La propriété position#

La propriété position permet de sortir un élément du flux et de créer une sorte de calque. Cet élément est ensuite déplaçable avec les propriétés top, bottom, left et right.

position: static#

C’est le comportement par défaut.

position: absolute#

L’élément sort du flux et superpose les autres.

Élément positionné à 100px du haut et à 300px de la gauche de l’écran.

#menu {
  position: absolute;
  top: 100px;
  left: 300px;
}

position: fixed#

Ce positionnement produit le même comportement qu’avec position: absolute. La seule différence est que la boite ne suit pas le défilement de la page. Elle reste fixe.

position: relative#

Ce positionnement permet 2 choses:

  • sortir la boite du flux mais sans superposition. L’élément reste en place. Le positionnement avec top, bottom, left et right se fait par rapport à l’endroit où devrait être la boite en position normale (et non par rapport à la page).
  • spécifier la boite comme nouvelle origine des éléments enfants en position: absolute.

position: sticky#

Le mode sticky est un mode hybride entre relative et fixed. L’élément est fixed, mais ne peut pas sortir de son parent. Donc, tant que l’élément est visuellement dans son parent (et que les conditions de positionnement sont respectées), l’élément ne bouge pas. Sinon, l’élement sticky suit le défilement avec son parent.

Empilement#

Lorsque plusieurs éléments utilisent la propriété position, il est possible de modifier l’ordre de superposition avec z-index.

L’élément 1 sera sous l’élément 2

#element1, #element2 {
  position: absolute;
}
#element1 {
  z-index: 5;
}
#element2 {
  z-index: 10;
}

La propriété float#

Lorsque un élément est placé en float, l’élément suivant prend l’espace disponible du coté inverse au float (si c’est possible). Les valeurs possibles sont left, right ou none.

Par exemple, une image positionnée en float: left, le texte suivant se positionnera sur la droite et contournera l’image.

La propriété float provoque une sortie du flux de l’élément et pose plusieurs problèmes:

  • un élément dont tous les enfants sont en float à une hauteur de 0px.
  • si l’on souhaite annuler l’effet du float, on utilise clear: left ou clear: right en fonction du float appliqué.

Cette propriété a été très utilisée pour le positionnement complet d’un site, même si elle n’a jamais été prévue pour cela.