Introduction au Développement HTML et CSS
Introduction au Développement HTML et CSS

Positionnement CSS : static, relative, absolute, fixed

Introduction

Bienvenue dans ce cours sur le positionnement CSS, un concept fondamental pour maîtriser la mise en page de vos sites web. Comprendre comment positionner les éléments est crucial pour aller au-delà du simple agencement par défaut et créer des designs complexes et réactifs.

Par défaut, les éléments HTML s'afficment selon le flux normal du document. Cela signifie qu'ils se placent l'un après l'autre, de gauche à droite pour les éléments en ligne et de haut en bas pour les éléments de bloc, comme si vous lisiez un texte. Cependant, ce flux ne suffit pas toujours. Que faire si vous voulez superposer des éléments, fixer une barre de navigation en haut de l'écran, ou placer un badge dans le coin d'une image ? C'est là que la propriété CSS position entre en jeu.

La propriété position vous permet de manipuler la façon dont un élément est placé sur la page. Elle peut prendre plusieurs valeurs, chacune ayant un comportement distinct et des implications sur le flux du document :

  • static
  • relative
  • absolute
  • fixed
  • (Il existe aussi sticky, mais nous nous concentrerons sur les quatre principales pour cette introduction.)

Pour chaque valeur de position (sauf static), vous pouvez utiliser les propriétés top, right, bottom, et left pour décaler l'élément par rapport à son point de référence. La propriété z-index permet quant à elle de gérer la superposition des éléments.

Plongeons dans les détails de chaque valeur.

Comprendre la Propriété position

1. position: static;

static est la valeur par défaut de tous les éléments HTML. Lorsque vous ne spécifiez aucune propriété position pour un élément, il se comporte comme static.

  • Comportement : L'élément est positionné selon le flux normal du document. Il se place naturellement après les éléments qui le précèdent et avant ceux qui le suivent.
  • Déplacement : Les propriétés top, right, bottom, et left n'ont aucun effet sur un élément avec position: static;.
  • Superposition : La propriété z-index n'a aucun effet sur un élément avec position: static;.
  • Utilisation : C'est le comportement le plus courant pour la majorité des éléments de votre page. Vous n'avez généralement pas besoin de le déclarer explicitement, sauf si vous voulez "réinitialiser" un élément qui aurait hérité d'une autre valeur de position.

Exemple simple :

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Position Statique</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        .boite {
            width: 100px;
            height: 100px;
            background-color: lightblue;
            border: 2px solid steelblue;
            margin-bottom: 10px;
            text-align: center;
            line-height: 100px;
            color: steelblue;
        }
        .boite-static {
            /* position: static; est la valeur par défaut, donc pas nécessaire de la déclarer */
            background-color: lightgreen;
            border-color: darkgreen;
            color: darkgreen;
        }
    </style>
</head>
<body>
    <h1>Exemple de `position: static;`</h1>
    <div class="boite">Boîte 1 (Défaut)</div>
    <div class="boite boite-static">Boîte 2 (Static Explicit)</div>
    <div class="boite">Boîte 3 (Défaut)</div>
</body>
</html>

Explication du code : Dans cet exemple, les trois boîtes s'affichent les unes après les autres, de haut en bas, car elles sont toutes des éléments de bloc avec la propriété position: static; (implicitement ou explicitement). Tenter d'appliquer top ou left à .boite-static n'aurait aucun effet visible.

2. position: relative;

relative permet de décaler un élément par rapport à sa position normale dans le flux du document, sans affecter les éléments qui l'entourent.

  • Comportement : L'élément est positionné selon le flux normal du document, mais ensuite il est décalé par rapport à sa position d'origine.
  • Déplacement : Les propriétés top, right, bottom, et left peuvent être utilisées pour décaler l'élément par rapport à sa position initiale.
    • top: 20px; déplace l'élément de 20px vers le bas par rapport à sa position initiale.
    • left: 30px; déplace l'élément de 30px vers la droite par rapport à sa position initiale.
  • Espace réservé : L'élément relative continue d'occuper l'espace dans le flux du document à sa position d'origine. C'est comme si une "ombre" de l'élément restait à sa place, et les autres éléments du document se positionnent en fonction de cette "ombre".
  • Superposition : La propriété z-index peut être utilisée pour contrôler l'ordre de superposition des éléments relative (et absolute, fixed, sticky).
  • Utilisation courante :
    • Décaler légèrement un élément sans perturber le reste de la page.
    • Conteneur pour les éléments position: absolute; (c'est son rôle le plus important et le plus fréquent).

Exemple :

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Position Relative</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        .conteneur {
            border: 2px dashed #ccc;
            padding: 10px;
            margin-bottom: 20px;
        }
        .boite {
            width: 100px;
            height: 100px;
            background-color: lightblue;
            border: 2px solid steelblue;
            margin-bottom: 10px; /* Pour les boîtes statiques */
            text-align: center;
            line-height: 100px;
            color: steelblue;
            display: inline-block; /* Pour les aligner côte à côte */
            vertical-align: top; /* Pour aligner en haut */
        }
        .boite-relative {
            position: relative;
            top: 20px; /* Déplace la boîte de 20px vers le bas */
            left: 30px; /* Déplace la boîte de 30px vers la droite */
            background-color: #ffcc99; /* Orange clair */
            border-color: #cc6600; /* Orange foncé */
            color: #cc6600;
        }
    </style>
</head>
<body>
    <h1>Exemple de `position: relative;`</h1>

    <div class="conteneur">
        <h2>Boîtes positionnées :</h2>
        <div class="boite">Boîte A (Défaut)</div>
        <div class="boite boite-relative">Boîte B (Relative)</div>
        <div class="boite">Boîte C (Défaut)</div>
    </div>
</body>
</html>

Explication du code : La "Boîte B (Relative)" est décalée de 20px vers le bas et 30px vers la droite. Vous remarquerez que l'espace qu'elle occupait initialement est toujours "réservé" dans le flux du document. C'est pourquoi la "Boîte C (Défaut)" se place comme si la Boîte B n'avait pas bougé, ce qui peut créer un chevauchement avec la Boîte B si elle est déplacée.

3. position: absolute;

absolute est l'une des valeurs les plus puissantes et souvent source de confusion. Un élément absolute est retiré du flux normal du document.

  • Comportement : L'élément absolute est sorti du flux. Les autres éléments se comportent comme s'il n'existait pas à sa position d'origine.
  • Déplacement : Les propriétés top, right, bottom, et left sont utilisées pour positionner l'élément. Mais la grande question est : par rapport à quoi ?
    • Un élément absolute se positionne par rapport à son plus proche ancêtre positionné (c'est-à-dire un ancêtre qui n'a pas position: static;). Cet ancêtre peut être relative, absolute, fixed, ou sticky.
    • Si aucun ancêtre positionné n'est trouvé, l'élément absolute se positionne par rapport au bloc de conteneur initial (généralement l'élément <html> ou <body>).
  • Espace réservé : L'élément absolute ne réserve plus d'espace dans le flux du document. C'est comme s'il était posé sur une couche distincte, flottant au-dessus ou en dessous du contenu normal.
  • Superposition : La propriété z-index a un effet complet et est souvent utilisée avec position: absolute;.
  • Utilisation courante :
    • Créer des pop-ups, des infobulles (tooltips), des menus déroulants.
    • Placer des icônes ou des badges à des emplacements précis (par exemple, un badge "Nouveau" dans le coin d'une carte produit).
    • Superposer des éléments.

Exemple : absolute à l'intérieur d'un conteneur relative

C'est le cas d'utilisation le plus courant et le plus recommandé pour absolute.

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Position Absolute</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            height: 1000px; /* Pour avoir de quoi scroller */
        }
        .boite-conteneur {
            position: relative; /* TRÈS IMPORTANT : ceci est l'ancêtre positionné */
            width: 300px;
            height: 200px;
            background-color: #f0f8ff; /* Bleu très clair */
            border: 2px dashed lightgray;
            margin: 50px auto; /* Centrer le conteneur */
            padding: 20px;
            text-align: center;
            line-height: 200px;
        }
        .boite-absolue {
            position: absolute;
            width: 80px;
            height: 80px;
            background-color: #ff6666; /* Rouge */
            border: 2px solid darkred;
            color: white;
            text-align: center;
            line-height: 80px;
            font-weight: bold;
            font-size: 0.9em;
            /* Positionnement par rapport au conteneur relatif */
            top: 10px;
            right: 10px;
        }
        .texte-normal {
            margin-top: 30px;
            padding: 15px;
            background-color: #f2f2f2;
            border: 1px solid #ddd;
        }
    </style>
</head>
<body>
    <h1>Exemple de `position: absolute;`</h1>

    <div class="boite-conteneur">
        Conteneur (position: relative;)
        <div class="boite-absolue">Badge</div>
    </div>

    <p class="texte-normal">
        Ce paragraphe est en dehors du conteneur. Notez que le "Badge" est positionné
        par rapport au conteneur `relative`, et que le conteneur (et ce paragraphe)
        ne sont pas affectés par la taille ou la position du badge, car le badge est sorti
        du flux normal.
    </p>

    <div style="height: 500px; background-color: #eee; margin-top: 50px; text-align: center; padding-top: 200px;">
        Contenu pour simuler un défilement
    </div>
</body>
</html>

Explication du code : Le div.boite-conteneur est défini avec position: relative;. Cela en fait le point de référence pour tous ses enfants ayant position: absolute;. Le div.boite-absolue est positionné avec top: 10px; et right: 10px; par rapport au bord supérieur-droit de son parent boite-conteneur. Le badge flotte au-dessus du conteneur et ne perturbe pas le flux des autres éléments.

4. position: fixed;

Les éléments fixed sont, comme absolute, retirés du flux normal du document. La différence majeure est leur point de référence.

  • Comportement : L'élément fixed est retiré du flux. Il est positionné par rapport au viewport (la fenêtre visible du navigateur).
  • Déplacement : Les propriétés top, right, bottom, et left sont utilisées pour positionner l'élément par rapport aux bords du viewport.
  • Défilement : Un élément fixed reste à la même position dans le viewport, même lorsque l'utilisateur fait défiler la page. Il "colle" à l'écran.
  • Espace réservé : L'élément fixed ne réserve pas d'espace dans le flux du document.
  • Superposition : La propriété z-index a un effet complet et est couramment utilisée pour s'assurer que les éléments fixes apparaissent au-dessus du contenu de la page.
  • Utilisation courante :
    • Barres de navigation (headers) qui restent visibles en haut de page.
    • Boutons "Retour en haut" (scroll-to-top).
    • Menus latéraux persistants.
    • Barres de pied de page (footers) toujours visibles.

Exemple :

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Position Fixed</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0; /* Important pour les éléments fixes */
            padding-top: 60px; /* Pour laisser de l'espace au header fixe */
            padding-bottom: 60px; /* Pour laisser de l'espace au footer fixe */
        }
        .header-fixe {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 50px;
            background-color: #333;
            color: white;
            text-align: center;
            line-height: 50px;
            z-index: 1000; /* Assure qu'il est au-dessus du contenu */
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
        }
        .footer-fixe {
            position: fixed;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 50px;
            background-color: #333;
            color: white;
            text-align: center;
            line-height: 50px;
            z-index: 1000; /* Assure qu'il est au-dessus du contenu */
            box-shadow: 0 -2px 5px rgba(0,0,0,0.2);
        }
        .contenu-principal {
            padding: 20px;
            max-width: 800px;
            margin: 20px auto;
            line-height: 1.6;
        }
        .section-longue {
            height: 400px;
            background-color: #f9f9f9;
            border: 1px dashed #ddd;
            margin-bottom: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2em;
            color: #666;
        }
    </style>
</head>
<body>
    <div class="header-fixe">Ma Super Barre de Navigation Fixe</div>

    <div class="contenu-principal">
        <h1>Bienvenue sur notre page de démonstration</h1>
        <p>
            Ce texte est le contenu principal de la page.
            Faites défiler vers le bas pour voir comment les barres de navigation fixes restent en place.
        </p>

        <div class="section-longue">
            Section 1 : Contenu qui défile
        </div>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
            Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
            Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
        </p>
        <div class="section-longue">
            Section 2 : Contenu qui défile
        </div>
        <p>
            Curabitur pretium tincidunt lacus. Nulla facilisi. In hac habitasse platea dictumst.
            Etiam faucibus cursus urna. Ut eu risus. Duis imperdiet est non nunc.
            Nulla est. Suspendisse eu lectus pellentesque, aliquet enim non, interdum urna.
            Aliquam erat volutpat. Praesent congue erat at massa. Aenean in magna et lorem egestas fermentum.
        </p>
        <div class="section-longue">
            Section 3 : Contenu qui défile
        </div>
        <p>
            Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
            Nulla facilisi. Integer lacinia sollicitudin massa. Cras in purus eu tellus ornare pharetra.
            Donec a scelerisque dui. Nullam ac convallis lorem. Maecenas ut arcu lacus.
            Mauris vel turpis et massa fermentum sollicitudin vel eu arcu.
            Pellentesque eget nulla et ipsum consectetur varius. Nulla semper ipsum id nibh.
        </p>
    </div>

    <div class="footer-fixe">Pied de page fixe - &copy; 2023</div>
</body>
</html>

Explication du code : Le div.header-fixe est positionné avec top: 0; et left: 0;, le plaçant en haut à gauche du viewport. Le div.footer-fixe est positionné avec bottom: 0; et left: 0;, le plaçant en bas à gauche du viewport. Lorsque vous faites défiler la page, ces deux éléments restent scotchés aux bords de la fenêtre du navigateur, offrant une expérience utilisateur cohérente. Notez l'utilisation de padding-top et padding-bottom sur le body pour empêcher le contenu de passer derrière les éléments fixes.

Concepts Associés

Le z-index

Lorsqu'on utilise les valeurs relative, absolute, fixed (et sticky), les éléments sont sortis du flux normal du document et peuvent se superposer. La propriété z-index permet de contrôler cet ordre de superposition.

  • Fonctionnement : z-index accepte des nombres entiers (positifs, négatifs ou zéro). Un élément avec un z-index plus élevé apparaîtra au-dessus des éléments avec un z-index plus faible.
  • Contexte d'empilement (Stacking Context) : z-index ne fonctionne que sur les éléments qui ont une propriété position autre que static. De plus, z-index fonctionne au sein de "contextes d'empilement". Un nouvel ancêtre positionné (relative, absolute, fixed, sticky) crée un nouveau contexte d'empilement. Les z-index d'éléments enfants sont relatifs à leur propre contexte d'empilement, et non nécessairement à tous les autres éléments de la page.
  • Valeur par défaut : La valeur par défaut de z-index est auto, ce qui signifie que l'élément hérite de la z-index de son parent, ou se comporte comme si z-index: 0; était appliqué.

Exemple de z-index :

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Z-index</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        .conteneur-zindex {
            position: relative;
            width: 300px;
            height: 200px;
            border: 2px solid #ccc;
            background-color: #f0f0f0;
            margin: 50px;
        }
        .boite-superposee {
            position: absolute;
            width: 150px;
            height: 150px;
            text-align: center;
            line-height: 150px;
            font-weight: bold;
            font-size: 1.2em;
            color: white;
        }
        .boite-rouge {
            background-color: #e74c3c; /* Rouge */
            top: 20px;
            left: 20px;
            z-index: 1; /* Sera derrière la bleue si la bleue a un z-index plus grand */
        }
        .boite-bleue {
            background-color: #3498db; /* Bleu */
            top: 60px;
            left: 60px;
            z-index: 2; /* Sera au-dessus de la rouge */
        }
    </style>
</head>
<body>
    <h1>Utilisation de `z-index`</h1>
    <div class="conteneur-zindex">
        <div class="boite-superposee boite-rouge">Boîte Rouge (z-index: 1)</div>
        <div class="boite-superposee boite-bleue">Boîte Bleue (z-index: 2)</div>
    </div>
</body>
</html>

Explication du code : Bien que la "Boîte Rouge" soit déclarée en premier dans le HTML (et devrait donc s'afficher par-dessus la "Boîte Bleue" par défaut si elles étaient au même niveau d'empilement et superposées), la "Boîte Bleue" a un z-index de 2, ce qui est supérieur à celui de la "Boîte Rouge" (1). Par conséquent, la "Boîte Bleue" apparaît au-dessus de la "Boîte Rouge".

Le Flux Normal du Document

Il est essentiel de bien comprendre ce qu'est le "flux normal du document" pour appréhender le positionnement CSS.

Le flux normal du document est l'ordre dans lequel les éléments sont affichés sur la page HTML par défaut, avant l'application de styles CSS qui modifieraient leur position.

  • Éléments de bloc (div, p, h1, etc.) : Occupent toute la largeur disponible et se placent les uns sous les autres.
  • Éléments en ligne (span, a, img, etc.) : Occupent uniquement la largeur de leur contenu et se placent les uns à côté des autres sur la même ligne. S'il n'y a plus de place, ils passent à la ligne suivante.

Quand vous utilisez position: static;, l'élément reste dans ce flux. Quand vous utilisez position: relative;, l'élément reste dans ce flux conceptuellement (il y réserve toujours sa place), mais est visuellement décalé. Quand vous utilisez position: absolute; ou position: fixed;, l'élément est retiré du flux. C'est comme s'il était aspiré hors du document et placé sur une couche séparée, flottant au-dessus ou en dessous. Les autres éléments se comportent alors comme si l'élément retiré n'avait jamais été là.

Conclusion

Le positionnement CSS est une pierre angulaire de la conception web. En maîtrisant static, relative, absolute, et fixed, ainsi que z-index, vous serez capable de :

  • position: static; : Le comportement par défaut, les éléments suivent le flux normal du document. Les propriétés de décalage (top, left, etc.) et z-index n'ont aucun effet.
  • position: relative; : L'élément est décalé par rapport à sa position d'origine dans le flux. Il laisse un vide à sa place d'origine. Idéal pour décaler légèrement un élément ou, plus important encore, servir de point de référence pour les éléments absolute enfants.
  • position: absolute; : L'élément est retiré du flux normal du document. Il se positionne par rapport à son ancêtre positionné le plus proche, ou par rapport au body/html s'il n'y en a pas. Ne laisse pas de vide. Parfait pour les pop-ups, badges, etc.
  • position: fixed; : L'élément est retiré du flux et positionné par rapport au viewport (la fenêtre du navigateur). Il reste en place même au défilement. Utile pour les barres de navigation persistantes.

N'oubliez pas que le positionnement peut être délicat au début. La clé est de pratiquer, d'expérimenter et d'utiliser l'inspecteur d'éléments de votre navigateur pour visualiser comment chaque propriété affecte le rendu de vos éléments. La compréhension du flux normal du document est la fondation sur laquelle toutes ces techniques de positionnement reposent.

Continuez à explorer et à coder !