Pied de page au bas de la page ou du contenu, selon la valeur la plus basse

92

J'ai la structure suivante:

<body>
    <div id="main-wrapper">
        <header>
        </header>
        <nav>
        </nav>
        <article>
        </article>
        <footer>
        </footer>
    </div>
</body>

Je charge dynamiquement le contenu dans le <article>javascript. Pour cette raison, la hauteur du <article>bloc peut changer.

Je veux que le <footer>bloc soit en bas de la page lorsqu'il y a beaucoup de contenu, ou en bas de la fenêtre du navigateur lorsqu'il n'y a que quelques lignes de contenu.

Pour le moment, je peux faire l'un ou l'autre ... mais pas les deux.

Alors, est-ce que quelqu'un sait comment je peux faire cela - faites en sorte que le <footer>reste du bas de la page / du contenu ou du bas de l'écran, selon celui qui est le plus bas.

Volonté
la source
Les gens voudraient-ils dire pourquoi ils ont voté à la baisse pour une question de 2 ans?
Sera
Allez, ça fait presque 6 ans ...
Will

Réponses:

99

Le pied de page collant de Ryan Fait est très agréable, mais je trouve que sa structure de base fait défaut *.


Version Flexbox

Si vous avez la chance d'utiliser flexbox sans avoir à prendre en charge les anciens navigateurs, les pieds de page collants deviennent trivialement faciles et prennent en charge un pied de page de taille dynamique.

L'astuce pour que les pieds de page collent au fond avec flexbox est d'avoir d'autres éléments dans le même conteneur fléchis verticalement. Tout ce qu'il faut, c'est un élément wrapper pleine hauteur avec display: flexet au moins un frère avec une flexvaleur supérieure à 0:

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

#main-wrapper {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

article {
  flex: 1;
}


Si vous ne pouvez pas utiliser flexbox, ma structure de base de choix est:

<div class="page">
  <div class="page__inner">
    <header class="header">
      <div class="header__inner">
      </div>
    </header>
    <nav class="nav">
      <div class="nav__inner">
      </div>
    </nav>
    <main class="wrapper">
      <div class="wrapper__inner">
        <div class="content">
          <div class="content__inner">
          </div>
        </div>
        <div class="sidebar">
          <div class="sidebar__inner">
          </div>
        </div>
      </div>
    </main>
    <footer class="footer">
      <div class="footer__inner">
      </div>
    </footer>
  </div>
</div>

Ce qui n'est pas si loin de:

<div id="main-wrapper">
    <header>
    </header>
    <nav>
    </nav>
    <article>
    </article>
    <footer>
    </footer>
</div>

L'astuce pour faire coller le pied de page consiste à ancrer le pied de page au rembourrage inférieur de son élément conteneur. Cela nécessite que la hauteur du pied de page soit statique, mais j'ai constaté que les pieds de page sont généralement de hauteur statique.

HTML:
<div id="main-wrapper">
    ...
    <footer>
    </footer>
</div>
CSS:
#main-wrapper {
    padding: 0 0 100px;
    position: relative;
}

footer {
    bottom: 0;
    height: 100px;
    left: 0;
    position: absolute;
    width: 100%;
}

Avec le pied de page ancré à #main-wrapper, vous devez maintenant avoir #main-wrapperau moins la hauteur de la page, sauf si ses enfants sont plus longs. Cela se fait en faisant #main-wrapperavoir un min-heightfichier 100%. Vous avez également de se rappeler que ses parents, htmlet bodydoivent être aussi grand que la page ainsi.

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

#main-wrapper {
    min-height: 100%;
    padding: 0 0 100px;
    position: relative;
}

footer {
    bottom: 0;
    height: 100px;
    left: 0;
    position: absolute;
    width: 100%;
}

Bien sûr, vous devriez remettre en question mon jugement, car ce code force le pied de page à tomber du bas de la page, même en l'absence de contenu. La dernière astuce consiste à changer le modèle de boîte utilisé par le #main-wrapperafin que le min-heightde 100%inclut le 100pxremplissage.

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

#main-wrapper {
    box-sizing: border-box;
    min-height: 100%;
    padding: 0 0 100px;
    position: relative;
}

footer {
    bottom: 0;
    height: 100px;
    left: 0;
    position: absolute;
    width: 100%;
}

Et là vous l'avez, un pied de page collant avec votre structure HTML d'origine. Assurez-vous simplement que le footer's heightest égal à #main-wrapper' s padding-bottom, et vous devriez être défini.


* La raison pour laquelle je trouve à redire à la structure de Fait est qu'elle définit les éléments .footeret .headersur différents niveaux hiérarchiques tout en ajoutant un .pushélément inutile .

zzzzBov
la source
J'avais besoin d'ajouter #main-wrapper *:first-child { margin-top: 0; }, sinon la page serait trop longue par la marge supérieure du premier enfant (provoquant une barre de défilement inutile sur les pages courtes).
Florian Brucker
Merci, @zzzzBov pour cette explication approfondie, et surtout pour avoir mentionné flex-direction (j'aurais aimé trouver cela plus tôt - m'aurait fait gagner quelques heures! :)
ea0723
La version Flexbox ne fonctionne pas pour moi dans IE11, mais l'autre approche me convient! Merci et +1!
Matt
@Matt, vous devez utiliser les préfixes de navigateur pour que flexbox fonctionne dans IE11. utilisez un outil comme le préfixeur automatique et vous n'aurez jamais à vous soucier de les ajouter manuellement.
zzzzBov du
2
Le lien de pied de page collant semble être rompu en raison de la conversion de son site en un avis In Memoriam pour lui. De plus, il n'y a pas de versions mises en cache en raison des paramètres de robots.txt
tzrlk
13

Le pied de page collant de Ryan Fait est une solution simple que j'ai utilisée à plusieurs reprises dans le passé.

HTML de base :

<div class="wrapper">
    <div class="header">
        <h1>CSS Sticky Footer</h1>
    </div>
    <div class="content"></div>
    <div class="push"></div>
</div>
<div class="footer"></div>

CSS :

* {
    margin: 0;
}
html, body {
    height: 100%;
}
.wrapper {
    min-height: 100%;
    height: auto !important;
    height: 100%;
    margin: 0 auto -142px; /* the bottom margin is the negative value of the footer's height */
}
.footer, .push {
    height: 142px; /* .push must be the same height as .footer */
}

/*

Sticky Footer by Ryan Fait
http://ryanfait.com/

*/

Traduire ceci pour être similaire à ce que vous avez déjà des résultats avec quelque chose du genre:

HTML :

<body>
    <div class="wrapper">
        <header>
        </header>
        <nav>
        </nav>
        <article>
        </article>
        <div class="push"></div>
    </div>
    <footer>
    </footer>
</body>

CSS:

* {
    margin: 0;
}
html, body {
    height: 100%;
}
.wrapper {
    min-height: 100%;
    height: auto !important;
    height: 100%;
    margin: 0 auto -142px; /* the bottom margin is the negative value of the footer's height */
}
footer, .push {
    height: 142px; /* .push must be the same height as .footer */
}

N'oubliez pas de mettre à jour le négatif sur la marge du wrapper pour qu'il corresponde à la hauteur de votre pied de page et appuyez sur div. Bonne chance!

Josh Mein
la source
4
J'aime la façon dont il a mis le commentaire en bas, approprié pour une solution de pied de page: D
Madara's Ghost
Il n'est pas nécessaire de modifier le balisage pour ce style particulier.
zzzzBov
@zzzzBov Je n'ai pas beaucoup de temps pour approfondir cette question pour le moment, mais que voulez-vous dire exactement?
Josh Mein
Je suis sur mon guichet automatique mobile, donc je ne peux pas écrire de réponse complète sinon je l'aurais déjà fait. Le commentaire était plus pour que je me souvienne d'ajouter une réponse plus tard.
zzzzBov
@JoshMein, j'ai ajouté une réponse qui explique comment faire coller le pied de page sans déranger la structure fournie.
zzzzBov
0

Je cherchais à résoudre ce problème sans ajouter de balisage supplémentaire, alors j'ai fini par utiliser la solution suivante:

article {
  min-height: calc(100vh - 150px); /* deduct the height or margins of any other elements within wrapping container*/
}

footer {
  height: 50px;
}

header {
   height: 50px;
}

nav {
  height: 50px;
}
<body>
  <div id="main-wrapper">
    <header>
    </header>
    <nav>
    </nav>
    <article>
    </article>
    <footer>
    </footer>
  </div>
</body>

Vous devez connaître les hauteurs d'en-tête, de navigation et de pied de page pour pouvoir définir la hauteur minimale de l'article. De cette manière, si l'article ne contient que quelques lignes de contenu, le pied de page restera en bas de la fenêtre du navigateur, sinon il ira en dessous de tout le contenu.

Vous pouvez trouver ceci et d'autres solutions publiées ci-dessus ici: https://css-tricks.com/couple-takes-sticky-footer/

Galina E
la source