web-dev-qa-db-fra.com

«position: collant» ne fonctionne pas lorsque «hauteur» est définie

Je crée une page de destination où l'utilisateur voit d'abord une zone principale avec un pied de page en dessous. Faire défiler plus bas révèle que le pied de page est un en-tête collant, et je vise à utiliser du CSS pur pour y parvenir. Pour obtenir l'apparence plein écran du contenu principal et du pied de page, j'ai défini la propriété height sur deux valeurs différentes: 92% et 8% (l'utilisation de vh ne fonctionne pas non plus). Peu importe le height que je spécifie dans mon CSS (différentes unités et toutes), mon pied de page div ne colle pas. Dès que je supprime la propriété height, cela fonctionne comme prévu.

Voici une capture d'écran de ma page avant en supprimant les propriétés height:

With %, landing

Comme vous pouvez le voir, il ne fait pas coller:

With %, scrolled

Après avoir supprimé les valeurs de la propriété height, il le fait stick:

Without %, scrolled

Sous le code correspondant:

html,
body {
  height: 100%;
  margin: 0;
}

#main {
  height: 92%;
}

#landing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
}

#landingContent {
  width: 20vw;
}

#footerNav {
  height: 8%;
  display: flex;
  align-items: center;
  position: -webkit-sticky;
  position: sticky;
  top: 0px;
}
<div id="main">
  <div id="landing">
    <div id="landingContent">
      <h1 class="logo">Logo</h1>
      <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
      <button>Button</button>
    </div>
  </div>
</div>
<div id="footerNav">
  <div id="footerNavContent">
    <h1 class="logo">Logo</h1>
  </div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

J'ai lu que l'utilisation de la propriété overflow peut être problématique, bien qu'elle ne soit pas présente et je n'ai rien entendu sur le fait que height soit un problème pour les autres. J'ai peut-être tort, bien sûr.

J'ai testé sur:

  • Firefox 61 (tous les soirs)
  • Safari 53 (aperçu technique)
  • Chrome 65

EDIT: Gros développement; suppression de la propriété height de #main conserve #footerNav collant.

8
Lachlan Shoesmith

Le problème ici concerne height, mais pas le height auquel vous avez pensé. Commençons d'abord par la définition de la position collante :

Un élément positionné de manière collante est un élément dont la valeur de position calculée est collante. Il est traité comme relativement positionné jusqu'à ce que son bloc contenant franchisse un seuil spécifié ( telles que la définition de top sur une valeur autre que auto) dans sa racine de flux (ou le conteneur dans lequel défile à l'intérieur) , auquel cas il est traité comme "bloqué" jusqu'à ce qu'il rencontre le bord opposé de son bloc contenant .

La partie importante ici est la dernière phrase qui explique que la position collante sera fin lorsque l'élément atteindra le bord de son bloc contenant et dans votre cas, le bloc contenant l'élément collant est le corps et vous définissez le corps sur height:100% et vous avez un débordement de contenu.

Ainsi, lorsque vous définissez la hauteur du principal à 92% et le pied de page à 8%, vous avez déjà créé le pied de page au bord opposé de son bloc contenant . Voici une illustration où j'ai ajouté une couleur d'arrière-plan au corps pour que vous puissiez voir clairement ceci:

html,
body {
  height: 100%;
  margin: 0;
}
html {
  background:white;
}
body {
  background:blue;
}

#main {
  height: 92%;
}
#landing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
}
#landingContent {
  width: 20vw;
}
#footerNav {
  height: 8%;
  display: flex;
  align-items: center;
  position: sticky;
  top: 0px;
}
<div id="main">
    <div id="landing">
        <div id="landingContent">
            <h1 class="logo">Logo</h1>
            <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
            <button>Button</button>
        </div>
    </div>
</div>
<div id="footerNav">
    <div id="footerNavContent">
        <h1 class="logo">Logo</h1>
    </div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

Comme vous pouvez le voir, le logo est déjà au bas du corps, il n'y a donc aucun moyen de le faire bouger comme collant. De plus, votre contenu déborde.

Maintenant, si vous diminuez un peu la hauteur du contenu principal, vous pouvez voir un petit comportement collant qui se terminera lorsque le pied de page atteindra le bas de la partie bleue (le body).

html,
body {
  height: 100%;
  margin: 0;
}
html {
  background:white;
}
body {
  background:blue;
}

#main {
  height: 82%;
}
#landing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
}
#landingContent {
  width: 20vw;
}
#footerNav {
  height: 8%;
  display: flex;
  align-items: center;
  position: sticky;
  top: 0px;
}
<div id="main">
    <div id="landing">
        <div id="landingContent">
            <h1 class="logo">Logo</h1>
            <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
            <button>Button</button>
        </div>
    </div>
</div>
<div id="footerNav">
    <div id="footerNavContent">
        <h1 class="logo">Logo</h1>
    </div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

Pour résoudre le problème, vous devez simplement éviter de définir height:100% au corps. Vous pouvez utiliser min-height à la place ou conservez sa hauteur auto. Vous pouvez également considérer vh unité pour le principal et le pied de page:

html,
body {
  /*height: 100%;
    no needed
  */ 
  margin: 0;
}
html {
  background:white;
}
body {
  background:blue;
}

#main {
  height: 92vh;
}
#landing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
}
#landingContent {
  width: 20vw;
}
#footerNav {
  height: 8vh;
  display: flex;
  align-items: center;
  position: sticky;
  top: 0px;
}
<div id="main">
    <div id="landing">
        <div id="landingContent">
            <h1 class="logo">Logo</h1>
            <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
            <button>Button</button>
        </div>
    </div>
</div>
<div id="footerNav">
    <div id="footerNavContent">
        <h1 class="logo">Logo</h1>
    </div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

Questions connexes pour plus de détails/exemples:

Pourquoi l'élément avec la position: collant ne colle pas au bas du parent?

Que sont les "boîtes de défilement"?

Si vous spécifiez `bottom: 0` pour position: sticky, pourquoi fait-il quelque chose de différent des spécifications?

9
Temani Afif