362 votes

Comment fonctionne la propriété "position : sticky ;"?

Je veux faire en sorte que la barre de navigation reste en haut de la fenêtre lorsqu'un utilisateur fait défiler la page, mais cela ne fonctionne pas et je ne sais pas pourquoi. Si vous pouvez m'aider, voici mon code HTML et CSS :

.container {
  min-height: 300vh;
}
.nav-selections {
  text-transform: uppercase;
  letter-spacing: 5px;
  font: 18px "lato",sans-serif;
  display: inline-block;
  text-decoration: none;
  color: white;
  padding: 18px;
  float: right;
  margin-left: 50px;
  transition: 1.5s;
}

.nav-selections:hover{
  transition: 1.5s;
  color: black;
}

ul {
  background-color: #B79b58;
  overflow: auto;
}

li {
  list-style-type: none;
}

<main class="container">
  <nav style="position: sticky; position: -webkit-sticky;">
    <ul align="left">
      <li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
      <li><a href="#/about" class="nav-selections">About</a></li>
      <li><a href="#/products" class="nav-selections">Products</a></li>
      <li><a href="#" class="nav-selections">Home</a></li>
    </ul>
  </nav>
</main>

19 votes

Position:sticky a besoin d'une coordonnée pour dire où coller

77 votes

Il faut également faire attention aux éléments parents. position: sticky peut cesser de fonctionner si elle se trouve à l'intérieur d'une flexbox, à moins que vous ne fassiez attention. et échouera également s'il y a un overflow: hidden ou overflow: auto entre lui et ce dans quoi il défile (corps Root ou ancêtre le plus proche avec overflow : scroll)

5 votes

@ user56reinstatemonica8 OMG mercikkkyou tellement de m'avoir parlé de la overflow: hidden et overflow: auto ! Je me suis gratté la tête pendant des jours pour essayer de faire fonctionner cette merde.

569voto

MarsAndBack Points 2030

Vérifier si un élément ancêtre a un débordement défini (ex. overflow:hidden ) ; essayez de le basculer. Vous devrez peut-être remonter l'arbre DOM plus haut que prévu =).

Cela peut affecter votre position:sticky sur un élément descendant.

67 votes

J'aimerais pouvoir te mettre en avant plusieurs fois ! Cela m'a piqué plus souvent que je ne veux bien l'admettre.

2 votes

C'est la bonne réponse. Cependant, il peut être difficile de trouver quel élément parent est à l'origine du problème. J'ai écrit un jquery script pour aider à identifier la propriété overflow sur les parents qui a identifié le problème (il suffit de l'exécuter dans votre console). Parce que le script est de quelques lignes, j'ai ajouté une réponse contenant le script ci-dessous.

9 votes

J'ai manqué le "s" dans votre "éléments parents"

356voto

Marvin Points 4362

Le positionnement statique est un hybride du positionnement relatif et du positionnement fixe. L'élément est traité comme un positionnement relatif jusqu'à ce qu'il franchisse un seuil spécifié, auquel cas il est traité comme un positionnement fixe.
...
Vous devez spécifier un seuil avec au moins un des éléments suivants top , right , bottom ou left pour que le positionnement collant se comporte comme prévu. Sinon, il sera impossible de le distinguer du positionnement relatif. [ source : MDN ]

Ainsi, dans votre exemple, vous devez définir la position à laquelle il doit s'accrocher à la fin en utilisant l'attribut top propriété.

html, body {
  height: 200%;
}

nav {
  position: sticky;
  position: -webkit-sticky;
  top: 0; /* required */
}

.nav-selections {
  text-transform: uppercase;
  letter-spacing: 5px;
  font: 18px "lato", sans-serif;
  display: inline-block;
  text-decoration: none;
  color: white;
  padding: 18px;
  float: right;
  margin-left: 50px;
  transition: 1.5s;
}

.nav-selections:hover {
  transition: 1.5s;
  color: black;
}

ul {
  background-color: #B79b58;
  overflow: auto;
}

li {
  list-style-type: none;
}

<nav>
  <ul align="left">
    <li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
    <li><a href="#/about" class="nav-selections">About</a></li>
    <li><a href="#/products" class="nav-selections">Products</a></li>
    <li><a href="#" class="nav-selections">Home</a></li>
  </ul>
</nav>

229 votes

En général, cette réponse n'est pas suffisante pour coller au travail, le parent ne devrait pas non plus avoir la propriété de débordement.

0 votes

Je vous remercie pour votre commentaire. Je suis d'accord avec vous que pour d'autres exemples que celui du PO, ma réponse pourrait ne pas être suffisante. Les autres réponses le soulignent :)

2 votes

Je pense que l'astuce est que le sticky position ne peut être appliqué qu'aux enfants qui appartiennent à un parent scrollable avec une hauteur connue, (un enfant direct dans une flexbox a une hauteur connue qui est calculée à partir d'autres éléments flex).

168voto

Miftah Mizwar Points 436

J'ai le même problème, et j'ai trouvé la réponse ici .

Si votre élément ne colle pas comme prévu, il faut d'abord vérifier les règles appliquées au conteneur.

Plus précisément, recherchez toute propriété de débordement définie sur les parents de l'élément. Vous ne pouvez pas utiliser : overflow: hidden , overflow: scroll ou overflow: auto sur le parent d'un position: sticky élément.

0 votes

C'est également la bonne réponse mais voyez aussi ma réponse qui permet d'identifier facilement le parent à l'origine du problème.

40 votes

Vous devez vérifier non seulement le conteneur parent le plus proche, mais aussi tous les éléments parents. s .

0 votes

Oui, voir ma réponse pour faire exactement cela et vérifier TOUS les parents très rapidement

50voto

Simon_Weaver Points 31141

Quelques autres choses que j'ai rencontrées :

Lorsque votre élément collant est un composant (angulaire, etc.)

  • Si l'élément "sticky" lui-même est un composant doté d'un sélecteur d'élément personnalisé, tel qu'un composant angulaire appelé <app-menu-bar> vous devrez ajouter les éléments suivants au fichier css du composant :

      :host { display: block; }     // or use flexbox

ou

    app-menu-bar  { display: block; }   // (in the containing component's css)

Safari on iOS in particular seems to require `display:block` even on the root element `app-root` of an angular application or it won't stick.
  • Si vous créez un composant et définissez le css à l'intérieur du composant (shadow DOM / styles encapsulés), assurez-vous que la balise position: sticky est appliqué au sélecteur "extérieur" (par exemple, le sélecteur de l'extérieur). app-menu-bar dans devtools devrait montrer la position collante) et non un niveau supérieur div sur le composant. Avec Angular, cela peut être réalisé avec la fonction :host dans le fichier CSS de votre composant.

      :host
      {
          position: sticky;
          display: block;   // this is the same as shown above
          top: 0;
          background: red;    
      }

Autre

  • Si l'élément qui suit votre élément collant a un arrière-plan solide, vous devez ajouter ce qui suit pour l'empêcher de glisser en dessous :

      .sticky-element { z-index: 100; }
      .parent-of-sticky-element { position: relative; }
  • Votre élément adhésif doit être avant votre contenu si vous utilisez top et après cela si vous utilisez bottom .

  • Il y a des complications quand on utilise overflow: hidden sur votre élément wrapper - en général, il tuera l'élément collant à l'intérieur. Mieux expliqué dans cette question

  • Les navigateurs mobiles peuvent désactiver les éléments collants/fixes positionnés lorsque le clavier à l'écran est visible. Je ne suis pas sûr des règles exactes (quelqu'un les connaît-il ?) mais lorsque le clavier est visible, vous regardez une sorte de "fenêtre" dans la fenêtre et vous ne pourrez pas facilement faire coller les éléments sur le haut de l'écran visible.

  • Assurez-vous que vous avez :

    position: sticky;

    et non

    display: sticky;

Divers problèmes de convivialité

  • Soyez prudent si votre conception prévoit de coller des éléments au bas de l'écran sur les appareils mobiles. Sur l'iPhone X, par exemple, une ligne étroite s'affiche pour indiquer la zone de balayage (pour revenir à la page d'accueil) - et les éléments situés dans cette zone ne sont pas cliquables. Par conséquent, si vous y collez quelque chose, assurez-vous de tester sur l'iPhone X que les utilisateurs peuvent l'activer. Un gros bouton "Acheter maintenant" ne sert à rien si les utilisateurs ne peuvent pas cliquer dessus !
  • Si vous faites de la publicité sur Facebook, la page web s'affiche dans un contrôle "webview" dans les applications mobiles de Facebook. En particulier lors de l'affichage de vidéos (où votre contenu ne commence que dans la moitié inférieure de l'écran), les éléments collants sont souvent complètement gâchés en plaçant votre page dans une fenêtre de défilement qui permet en fait à vos éléments collants de disparaître du haut de la page. Veillez à effectuer des tests dans le contexte d'une publicité réelle et pas seulement dans le navigateur du téléphone ou même dans celui de Facebook, qui peuvent tous se comporter différemment.

0 votes

@Sergey Je ne suis pas tout à fait sûr de savoir lequel de ces deux éléments est le plus important. display: block et position: relative déclenche le comportement correct dans Safari - semblait-il que seul display: block était nécessaire ? Bien sûr, cela ne fait pas de mal d'avoir les deux spécifiés.

3 votes

Juste display: block était suffisant

1 votes

Vous êtes une star :)

35voto

danday74 Points 15895

Ceci est la suite des réponses de MarsAndBack et Miftah Mizwar.

Leurs réponses sont correctes. Cependant, il est difficile d'identifier le ou les ancêtres problématiques.

Pour rendre cela très simple, il suffit d'exécuter ce jQuery script dans la console de votre navigateur et il vous indiquera la valeur de la propriété overflow sur chaque ancêtre.

$('.your-sticky-element').parents().filter(function() {
    console.log($(this));
    console.log($(this).css('overflow'));
    return $(this).css('overflow') === 'hidden';
});

Lorsqu'un ancêtre n'a pas overflow: visible modifier son CSS pour qu'il le fasse !

De plus, comme indiqué ailleurs, assurez-vous que votre élément collant a ceci dans le CSS :

.your-sticky-element {
    position: sticky;
    top: 0;
}

2 votes

C'était très utile. J'ai pu identifier rapidement l'élément parent qui avait une valeur de overflow: invisible .

5 votes

Si vous n'avez pas de jQuery sur votre page, vous pouvez exécuter ce petit extrait dans la console pour l'ajouter : (async function() { let response = await fetch('https://code.jquery.com/jquery-3.3.1.min.js'); let script = await response.text(); eval(script); })();

13 votes

Vous pouvez également utiliser ce snippet qui ne nécessite pas JQuery pour trouver le parent de débordement non "visible" : var p = $0.parentElement; while(p != null) { var ov = getComputedStyle(p).overflow; if(ov !== 'visible') console.warn(ov, p); else console.log(ov, p); p = p.parentElement; }$0 est le dernier élément sélectionné dans les outils de développement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X