Positionnement CSS et Systemes de Coordonnees

La plupart des tutoriels vous disent ce que fait position: absolute. Celui-ci vous montre comment il pense -- comme un systeme de coordonnees avec origine, axes et containing block.

Demo en Direct : Basculer les Modes de Positionnement

Choisissez une valeur de position et faites glisser les curseurs. La boite rouge se repositionne et l'affichage des coordonnees vous montre exactement ou se trouve son point d'origine et comment top/left se traduisent en decalages de pixels. C'est le moyen le plus rapide d'interioriser la difference entre relative et absolute.

10px 10px
Conteneur (position: relative)
Boite
Origine: coin superieur-gauche du containing block
position: relative | top: 10px left: 10px

Le Positionnement comme Systeme de Coordonnees, Pas Regle de Layout

Voici le changement mental qui fait cliquer le positionnement CSS : top, right, bottom et left sont des coordonnees, pas des marges. Quand vous ecrivez top: 50px, vous placez l'element a 50 pixels en dessous d'un point d'origine specifique. La question est : origine de quoi ?

Chaque element positionne vit dans un containing block (bloc conteneur) -- la boite qui definit son origine de coordonnees. Voyez-le comme le point (0, 0) pour cet element. Le containing block est different selon la valeur de position que vous utilisez, et c'est la chose la plus confuse du positionnement CSS.

Pour position: absolute et position: fixed, l'element est retire entierement du flux normal du document. Ses coordonnees sont mesurees par rapport au containing block, pas par rapport a ses freres ou parent dans le flux normal. C'est pourquoi un element en position absolue peut superposer d'autre contenu -- il a quitte le systeme de coordonnees du flux du document.

Les Cinq Valeurs de position, Selon une Perspective de Coordonnees

ValeurOrigine des Coordonnees (Containing Block)Dans le Flux Normal ?Usage Commun
static (par defaut)Pas d'origine -- top/left ignoresOui, suit l'ordre du documentTout ce qui n'a pas besoin de positionnement explicite
relativeLa position originale de l'element dans le fluxOui, mais decale visuellement (espace original preserve)Ajustements fins, etablir un containing block pour les enfants
absoluteAncetre positionne le plus proche (tout non-static), ou le containing block initialNon -- retire du flux, les autres elements remplissent son espaceInfobulles, badges, overlays positionnes relatif au parent
fixedLe viewport (fenetre du navigateur), sauf si un ancetre a transform/filter/perspectiveNon -- retire du fluxBarres de navigation fixes, boutons flottants, bannieres de cookies
stickyAncetre de defilement le plus proche ; bascule entre relatif-au-flux et fixe au defilementOui, jusqu'a atteindre le seuil de defilementEn-tetes de tableau, navigation de section qui reste au defilement

Le tableau ci-dessus est la reference. Deballonnen maintenant les trois choses qui causent le plus de confusion dans la pratique.

Containing Block : Le Concept que la Plupart des Tutoriels Passent sous Silence

Si vous devez retenir une chose de cette page, que ce soit celle-ci : position: absolute n'est pas relatif a l'element parent. Il est relatif a l'ancetre positionne le plus proche -- le premier ancetre en remontant l'arbre qui a position avec une valeur autre que static.

Cela piege tout le monde la premiere fois. Vous mettez position: absolute sur un enfant, vous definissez top: 0; left: 0;, et l'element s'envole au coin de la page au lieu du coin du parent. La raison : le parent a position: static (par defaut), donc le navigateur remonte l'arbre cherchant un ancetre positionne, n'en trouve aucun, et utilise le viewport comme containing block.

I am lost

La solution est toujours la meme : ajoutez position: relative au parent. Cela etablit le parent comme containing block, et maintenant le top/left de l'enfant sont mesures depuis le bord de padding du parent.

I am anchored

Regle generale : si vous utilisez position: absolute sur un enfant, le parent a presque surement besoin de position: relative sans decalage. Ce motif -- parent relative, enfant absolute -- est le cheval de bataille du positionnement d'overlays, d'infobulles et de badges.

Le Piege du transform

Voici un piege qui a fait perdre des heures aux developpeurs : si vous mettez transform, perspective, filter, backdrop-filter, will-change: transform ou contain: paint sur un element, il devient le containing block de tous les descendants en position: fixed. Pas seulement les enfants directs -- n'importe quel descendant.

Cela signifie que votre barre de navigation en position fixe defile soudainement avec la page au lieu de rester en place, parce qu'un ancetre 10 niveaux au-dessus a un transform: translateZ(0) pour l'acceleration GPU. La solution est de comprendre ce qui cree des containing blocks :

/* This ancestor looks innocent... */
.site-wrapper {
  transform: translateZ(0); /* GPU optimization */
}

/* ...but it hijacks fixed positioning for ALL descendants */
.nav {
  position: fixed;
  top: 0;
  /* BUG: this is now relative to .site-wrapper,
     not the viewport. It scrolls with the page. */
}

Les proprietes qui creent un containing block pour les descendants en position: fixed : transform, perspective, filter, backdrop-filter (ou supporte), will-change avec valeur transform/perspective/filter, et contain: paint ou contain: layout. Si votre element fixed se comporte mal, remontez l'arbre DOM et verifiez ces proprietes.

Stacking Contexts : Le Systeme de Coordonnees de l'Axe Z

Le positionnement gere X et Y. z-index gere Z -- mais il ne fonctionne pas comme la plupart des gens le pensent. z-index ne fonctionne que dans un stacking context (contexte d'empilement), et un stacking context n'est pas la meme chose que le document.

Voyez un stacking context comme une couche isolee. Les elements a l'interieur peuvent s'empiler relativement entre eux, mais la couche entiere est positionnee comme une unite contre les autres couches. Donc un z-index: 9999 dans un stacking context peut toujours etre derriere un z-index: 1 dans un stacking context different de niveau superieur.

Qu'est-ce qui cree un stacking context ?

La consequence pratique : si votre modale avec z-index: 9999 apparait derriere un menu deroulant avec z-index: 10, c'est presque certainement parce que la modale est dans un stacking context (cree par un transform ou opacity sur un ancetre) qui se trouve lui-meme sous le stacking context du menu deroulant. Vous ne pouvez pas regler ca en augmentant le z-index de la modale -- vous devez sortir la modale du stacking context de l'ancetre, ou supprimer la propriete qui le cree.

Unites de Viewport et Positionnement Responsive

Quand vous utilisez position: fixed ou position: absolute avec des decalages en pourcentage, ces pourcentages sont relatifs aux dimensions du containing block, pas a la taille de l'element lui-meme. top: 50% signifie 50% de la hauteur du containing block.

Les unites de viewport vous permettent de positionner relativement a la fenetre reelle du navigateur :

UniteRelatif ACas d'Usage
vw / vh1% de la largeur / hauteur du viewportOverlays plein ecran, barres laterales fixes
dvw / dvh1% du viewport dynamique (tient compte de la barre URL mobile)Positionnement fixe mobile-first -- evite le saut de la barre URL de Safari iOS
svw / svh1% du viewport minimal possibleElements qui ne doivent jamais etre caches derriere l'UI du navigateur
lvw / lvh1% du viewport maximal possibleImages de fond plein cadre

Les unites dvh / dvw / svh / lvh sont plus recentes et resolvent le probleme de Safari mobile ou 100vh inclut la zone derriere la barre URL, causant la coupure du contenu. Utilisez 100dvh au lieu de 100vh pour les elements qui doivent remplir le viewport visible.

Motifs Reels qui Fonctionnent Vraiment

Overlay de Modale Centre

Le motif pour une modale centree qui fonctionne partout. La cle est de combiner position: fixed avec inset: 0 (raccourci pour les quatre cotes) et place-items: center :

.modal-backdrop {
  position: fixed;
  inset: 0; /* top:0; right:0; bottom:0; left:0 */
  background: rgba(0,0,0,.5);
  display: grid;
  place-items: center; /* centers the modal */
  z-index: 1000;
}
.modal {
  background: #fff;
  border-radius: 12px;
  padding: 2rem;
  max-width: 90vw;
  max-height: 90vh;
  overflow: auto;
}

En-tete de Tableau Sticky

position: sticky sur un en-tete de tableau est le moyen le plus propre de garder les etiquettes de colonne visibles pendant le defilement. L'astuce : top: 0 definit quand il s'accroche, et le conteneur de defilement doit etre le parent de defilement du tableau :

.table-scroll {
  max-height: 400px;
  overflow: auto;
}
.table-scroll thead th {
  position: sticky;
  top: 0;
  background: #fff; /* must be opaque */
  z-index: 1;
}

Infobulle au Survol

Le motif parent relative / enfant absolute pour les infobulles. L'infobulle est cachee par defaut et revelee au survol :

.tooltip-trigger {
  position: relative; /* containing block for tooltip */
  display: inline-block;
}
.tooltip {
  position: absolute;
  bottom: 100%; /* sits above the trigger */
  left: 50%;
  transform: translateX(-50%); /* horizontal center */
  margin-bottom: 8px;
  padding: .5rem .75rem;
  background: #1a1a1a;
  color: #fff;
  border-radius: 6px;
  font-size: .85rem;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s;
}
.tooltip-trigger:hover .tooltip {
  opacity: 1;
}

Cadre de Decision : Quelle position Utiliser

Arretez de memoriser ce que fait chaque valeur. Utilisez ce flux de decision a la place :

L'element doit-il superposer un autre contenu ou sortir du flux normal ?

  Non → Utilisez static (par defaut). Utilisez Flexbox ou Grid pour le layout.

  Oui, temporairement lors d'interaction (menu deroulant, infobulle) → relative sur le parent, absolute sur l'enfant.

L'element doit-il rester visible au defilement de la page ?

  Oui, toujoursfixed (verifiez les transform sur les ancetres !)

  Oui, mais seulement apres avoir defile au-dela d'un pointsticky.

Voulez-vous seulement decaler legerement un element de sa position normale ?

  Ouirelative avec de petits decalages top/left.

FAQ

Pourquoi mon element z-index:9999 apparait derriere un element z-index:1 ?

Stacking contexts. Votre element z-index:9999 est probablement dans un stacking context (cree par transform, opacity ou position:fixed sur un ancetre) qui se trouve sous le stacking context contenant l'element z-index:1. Augmenter le numero n'aidera pas. Deplacez l'element hors de l'ancetre qui cree le stacking context, ou supprimez cette propriete.

Pourquoi mon element position:fixed defile avec la page ?

Un ancetre a transform, filter, perspective, will-change ou contain. Ces proprietes creent un containing block pour les descendants fixed, les faisant se comporter comme absolute. Trouvez et supprimez la propriete sur l'ancetre, ou deplacez l'element fixed plus haut dans le DOM.

Quelle est la difference entre position: relative et un decalage de margin ?

Les deux deplacent l'element visuellement, mais position: relative preserve l'espace original de l'element dans le layout -- les autres elements ne se refluident pas pour combler le vide. Un margin decale l'element et provoque le refluidage des elements environnants. Utilisez relative quand vous voulez decaler sans affecter les freres.

Devrais-je utiliser inset au lieu de top/right/bottom/left ?

Oui, pour le code moderne. inset: 0 est le raccourci de top:0; right:0; bottom:0; left:0. Vous pouvez aussi faire inset: 10px 20px pour vertical/horizontal. C'est plus court, plus lisible et a un bon support (97%+).

position affecte-t-il les performances ?

position: fixed et position: sticky peuvent causer des repeints plus frequents pendant le defilement car le navigateur doit les repositionner a chaque frame. Ajouter will-change: transform peut aider le navigateur a optimiser, mais une utilisation excessive de will-change augmente la consommation memoire. Testez sur de vrais appareils si vous voyez des saccades de defilement.

Comment positionner quelque chose relatif au centre du viewport ?

Utilisez position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); ou l'approche moderne : position: fixed; inset: 0; margin: auto; width: votre-largeur; height: votre-hauteur;. Les deux centrent l'element. L'approche transform est plus flexible pour les tailles inconnues.

Continuer: Le positionnement CSS est une moitie de l'histoire des coordonnees d'ecran. Voici l'autre moitie :

JavaScript Coordonnees Souris — Comment clientX, offsetX, pageX, screenX se rapportent aux elements positionnes

Pixels Physiques vs Logiques — Pourquoi vos elements positionnes s'affichent differemment sur les ecrans HiDPI

Guide de Mise a l'Echelle DPI — Comment la mise a l'echelle du systeme affecte les coordonnees CSS

Guide Technique des Coordonnees d'Ecran — Analyse approfondie du device pixel ratio et des transformations de coordonnees

Accueil