Cours CSS / position : relative, absolute, fixed et sticky

La propriété position change la manière dont une boîte est positionnée et comment elle participe au flux normal. relative conserve son espace d'origine, absolute et fixed quittent le flux, et sticky combine le placement en flux normal avec un maintien à l’écran limité par son conteneur lors du défilement.

Comparez les modes de positionnement avec static

valeur Espace d'origine du flux normal Critères de position et de défilement
static Conservé Flux normal ; les décalages top et left ne s’appliquent pas.
relative Conservé Se déplacer selon un décalage à partir de l'emplacement d'origine
absolute non occupé Généralement le bloc contenant de l'ancêtre positionné le plus proche.
fixed non occupé Fenêtre d'affichage normale. Certaines propriétés ancestrales peuvent changer les critères
sticky Conservé Limites des ancêtres et blocs contenant du mécanisme de défilement à proximité

Le flux normal est la mise en page dans laquelle les éléments occupent de l'espace selon les règles de formatage du document. Le texte suivant un élément positionné de manière absolue ne se déplace pas automatiquement pour lui faire de la place. Lorsqu'un élément quitte le flux, le contenu suivant peut occuper son ancien espace. Prévenez le chevauchement grâce à la structure de mise en page ou à un remplissage approprié. Comparez le positionnement avec display : block, inline, inline-block et masquage pour comprendre cette différence.

Les décalages dépendent du mode de positionnement. Avec un positionnement relatif, top: 16px déplace la boîte de 16px vers le bas par rapport à sa position d'origine. Avec un positionnement absolu, top se mesure à partir de son bloc contenant de référence. Le même nombre représente donc différentes relations de positionnement. Voir MDN: position.

Conservez l'espace original avec relative

relative ne recalcule pas la position des éléments voisins. Même si vous déplacez une carte un peu vers le bas, la position de départ originale de la carte suivante est maintenue. Il peut donc y avoir chevauchement avec des éléments en dessous ou afficher un espace vide au-dessus. Si le but est de changer l'espacement de tout le document, vérifiez d'abord si la marge, le padding et le gap sont appropriés plutôt que d'utiliser top relatif.

Une autre utilisation de relative est de créer une référence de positionnement absolu pour les enfants. Si vous écrivez seulement position: relative pour le parent sans spécifier de décalage, le parent lui-même ne bougera pas et deviendra la base pour le badge enfant. Spécifier une position ne signifie pas immédiatement que tous les éléments se chevauchent ou sortent du flux du document.

Trouver le bloc contenant pour absolute

Un élément en position: absolute utilise généralement le bloc contenant établi par son ancêtre positionné le plus proche, c’est-à-dire un ancêtre dont position diffère de static. Appliquer position: relative à la carte et position: absolute, top et right à son badge permet de placer celui-ci dans la carte. Sans cet ancêtre, le badge peut se référer à une zone plus extérieure, jusqu’au bloc contenant initial. Des propriétés telles que transform peuvent aussi établir un bloc contenant : vérifiez les propriétés des ancêtres au-delà de leur seule valeur de position.

Un parent avec seulement des enfants absolus n'ajoute pas la hauteur de ses enfants à la hauteur du contenu dans le flux normal. Des problèmes où le parent semble avoir une hauteur nulle ou où les bordures sont effondrées peuvent survenir même si les enfants sont visibles. Si le contenu doit déterminer naturellement la hauteur du parent, il est plus facile de la gérer en plaçant les enfants dans le flux et en rendant uniquement les petits badges superposés absolus.

Comparer le flux normal et un badge absolu

Enregistrez le code ci-dessous sous le nom position-flow.html. Les trois sections conservent le même ordre HTML : élément précédent, cible, élément suivant. Les décalages top et right de 12px du badge se réfèrent à la carte. Le padding supérieur de 64px réserve de la place pour éviter que le badge ne recouvre le texte.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>position-flow.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.flow { border: 2px dashed #789; margin-bottom: 40px; margin-right: 24px; }
 .flow > div { height: 56px; padding: 12px; background: #e8f5de; }
 .flow .target { background: #dceefa; }
 .relative .target { position: relative; top: 16px; left: 20px; }
 .absolute { position: relative; }
 .absolute .target { position: absolute; top: 16px; left: 20px; }
 .card { position: relative; padding: 64px 20px 20px; background: #dceefa; max-width: 600px; }
 .badge { position: absolute; top: 12px; right: 12px; padding: 4px 12px; background: #ffe4b5; }
  </style>
</head>
<body>
<h1>Does the original space remain?</h1>
<h2>static</h2><div class="flow static"><div>Front element</div><div class="target">Target</div><div class="after">Back element</div></div>
<h2>relative</h2><div class="flow relative"><div>Front element</div><div class="target">Target</div><div class="after">Back element</div></div>
<h2>absolute</h2><div class="flow absolute"><div>Front element</div><div class="target">Target</div><div class="after">Back element</div></div>
<h2>Badge inside the card</h2><div class="card"><span class="badge">News</span><p>The badge sits at the top right of the card. Top padding separates it from the text.</p></div>
</body>
</html>
  1. Comparez la position de l'élément suivant dans les sections statique et relative. Même si la cible relative est déplacée vers le bas de 16px, l'espace de placement pour l'élément arrière est maintenu par rapport à la position initiale de la cible. Confirmez en ne changeant que le top à 0 puis en le restaurant à 16px.
  2. Une section absolue sort la cible du flux et place l'élément suivant immédiatement après l'élément précédent. Si vous changez la position de .absolute .target en static, la hauteur du parent augmentera de la hauteur de la cible. Après comparaison, rétablissez absolute.
  3. Essayez de supprimer uniquement position: relative de .card du badge de la carte. Après avoir confirmé que le badge n'est plus ancré dans le coin supérieur droit de la carte, restaurez-la immédiatement. Les autres conditions ne changent pas.
  4. Allongez le texte du badge et vérifiez l'espacement entre elles et le texte principal. absolute ne repousse pas automatiquement le contenu de la carte, donc si votre badge peut avoir plusieurs lignes, vous devriez considérer si un simple padding fixe est suffisant. Après l'exercice, revenez aux lettres d'origine.

Distinguer fixed et sticky pendant le défilement

fixed est généralement ancré à la fenêtre d'affichage, maintenant sa position à l'écran même lorsque le document est fait défiler. Il peut être utilisé pour de petits éléments opérationnels, comme le lien de retour en haut situé en bas à droite de l'écran. Il n'occupe pas d'espace dans le flux, donc si vous avez une barre sticky, assurez-vous de laisser suffisamment d'espace pour qu'elle n'obscurcisse pas la fin du texte du corps et l’élément qui reçoit le focus.

Le transform d'un ancêtre peut établir le bloc contenant pour un descendant fixé, remplaçant la référence habituelle à la fenêtre d'affichage. Si un élément fixé se déplace avec une boîte particulière, inspectez les propriétés de l'ancêtre telles que transform et filter. Cet exemple exclut ces propriétés pour démontrer le positionnement par rapport à la fenêtre d'affichage.

Pour observer le maintien avec sticky, au moins un décalage sur l’axe concerné doit avoir une valeur différente de auto, par exemple top: 0. Le titre n'est pas fixé à l'écran dès le départ, mais reste plutôt dans sa propre position dans le flux et s'attache lorsqu'il atteint la bordure supérieure lors du défilement. Lorsqu'il atteint la fin de son parent, il se déplace le long de ses limites et ne continue pas à flotter au-dessus de la section suivante.

sticky se réfère à l’ancêtre le plus proche doté d’un mécanisme de défilement. overflow: auto, overflow: scroll et overflow: hidden peuvent créer cette référence, même si cet ancêtre n’est pas la zone que l’utilisateur fait réellement défiler. Le maintien peut aussi rester imperceptible si la hauteur du titre laisse trop peu de place dans son parent. Identifiez le mécanisme de défilement, le bloc contenant et l’espace de déplacement avant de modifier overflow.

Observer le seuil de sticky et les limites du parent

Enregistrez l'exemple sous position-scroll.html. Une zone d'introduction d'au moins 320px de hauteur maintient le titre collant en dessous du haut initial de la fenêtre. Le chapitre et la section suivante ont suffisamment de hauteur pour observer quand le collage commence et quand la limite du parent le libère.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>position-scroll.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
body { margin: 0; padding-bottom: 80px; }
 .intro { min-height: 320px; padding: 24px; background: #eef2f6; }
 .chapter { min-height: 760px; background: #e8f5de; }
 .sticky { position: sticky; top: 0; margin: 0; padding: 16px; background: #dceefa; border-bottom: 2px solid #789; }
 .chapter p { padding: 16px; }
 .tail { min-height: 900px; padding: 24px; background: #fff2df; }
 .fixed { position: fixed; right: 16px; bottom: 16px; padding: 12px; background: #fff; border: 2px solid #145f8f; }
  </style>
</head>
<body>
<div class="intro" id="top"><h1>A heading that sticks while scrolling</h1><p>The heading below starts in normal flow. It sticks when it reaches the top of the screen and remains within its parent at the end of the chapter.</p></div>
<section class="chapter"><h2 class="sticky">Chapter heading</h2><p>This content is inside the chapter. The extra height lets you observe how long its heading remains sticky.</p></section>
<section class="tail"><h2>Another section</h2><p>Check whether the previous chapter's heading stays above this section.</p></section>
<a class="fixed" href="#top">Back to top</a>
</body>
</html>
  1. Avant de faire défiler, assurez-vous que le titre se trouve sous la zone d'introduction. Faites défiler la page lentement afin que le titre reste en place lorsqu'il atteint le haut de l'écran. Le lien de retour en haut, en bas à droite est à la même position sur l'écran depuis le début.
  2. Faites défiler le chapitre et descendez vers une autre zone. Les titres collants sont poussés jusqu'à la fin du chapitre parent, mais les liens fixes restent visibles. Cliquez sur le lien pour revenir à la zone d'introduction.
  3. Si vous changez seulement le top de .sticky en auto, il n’y aura plus de seuil de maintien sur l’axe vertical et il défilera comme un flux normal. Après confirmation, rétablissez à 0.
  4. Ajoutez simplement overflow: hidden à votre .chapter pour voir les résultats sticky lors du défilement de la fenêtre lorsque l'ancêtre le plus proche avec un mécanisme de défilement est changé. Après comparaison, supprimez la déclaration ajoutée.

Diagnostiquer un positionnement inattendu

Si l'ordre d'empilement ne change pas même après avoir spécifié la position, vérifiez le z-index CSS et les contextes d'empilement .

  1. Tout d'abord, vérifiez s'il reste de l'espace. Le placement des éléments environnants varie selon qu'ils sont relatifs/sticky ou absolus/fixes.
  2. Vérifiez la position réelle et les valeurs appliquées top·right·bottom·left dans les outils de développement. Vérifiez également quelles règles et quelles media queries ont la priorité.
  3. absolute vérifie l'ancêtre de base, et fixed vérifie la propriété de l'ancêtre qui modifie le bloc contenant. sticky vérifie la frontière, l'ancêtre de défilement, la hauteur du parent et la marge de mouvement.
  4. Si les coordonnées sont correctes mais sont masquées, distinguez entre un problème de localisation et un ordre de superposition/une troncature par overflow. Un grand z-index ne résout pas toutes les occultations.