web-dev-qa-db-fra.com

Définissez div à la hauteur restante à l'aide de CSS avec des diviseurs de hauteur inconnus au-dessus et en dessous

Est-il possible de faire en sorte que le wrapper remplisse la hauteur de la fenêtre (pas de défilement) et le div central défilable sans déconner avec les pixels et le javascript?

<div id="wrapper">
  <h1>Header</h1>
  <div id="center">
    <div style="height:1000px">high content</div>
  </div>
  <div id="footer">Footer</div>
</div>

Fondamentalement, je veux que l'en-tête soit visible en haut et le pied de page soit toujours visible en bas et ait un contenu défilable au centre qui occupe la hauteur restante.
Les hauteurs des en-têtes, pieds de page et divisions centrales sont toutes inconnues (pas de px ou de% défini, c'est-à-dire taille de police variable ou remplissage). Est-ce possible avec du CSS pur?

55
danial

Une solution multi-navigateur dérivée de Dan Dascalesc réponse:

http://jsfiddle.net/Uc9E2

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}
.l-fit-height {
    display: table;
    height: 100%;
}
.l-fit-height-row {
    display: table-row;
    height: 1px;
}
.l-fit-height-row-content {
    /* Firefox requires this */
    display: table-cell;
}
.l-fit-height-row-expanded {
    height: 100%;
    display: table-row;
}
.l-fit-height-row-expanded > .l-fit-height-row-content {
    height: 100%;
    width: 100%;
}
@-moz-document url-prefix() {
    .l-scroll {
        /* Firefox requires this to do the absolute positioning correctly */
        display: inline-block;
    }
}
.l-scroll {
    overflow-y: auto;
    position: relative;
    height: 1000px;
}
.l-scroll-content {
    position: absolute;
    top: 0;
    bottom: 0;
    height: 1000px;
    min-height:100px;
}
<div class="l-fit-height">
    <section class="l-fit-height-row">
        <div class="l-fit-height-row-content">
            <p>Header</p>
        </div>
    </section>
    <section class="l-fit-height-row-expanded">
        <div class="l-fit-height-row-content l-scroll">
            <div class="l-scroll-content">
                <p>Foo</p>
            </div>
        </div>
    </section>
    <section class="l-fit-height-row">
        <div class="l-fit-height-row-content">
            <p>Footer</p>
        </div>
    </section>
</div>
5
danial

MISE À JOUR 2014 : La façon moderne de résoudre ce problème de mise en page est de tiliser le modèle CSS flexbox . Il est pris en charge par tous les principaux navigateurs et IE11 +.


2012: La bonne façon de le faire avec CSS seul est d'utiliser display: table et display: table-row. Ce sont pris en charge par tous les principaux navigateurs , en commençant par IE8. C'est pas en utilisant des tableaux pour l'affichage. Vous utiliserez des divs:

html, body {
    height: 100%;
    margin: 0;
}
.wrapper {
    display: table;
    height: 100%;
    width: 100%;
    background: yellow;  /* just to make sure nothing bleeds */
}
.header {
    display: table-row;
    background: gray;
}
.content {
    display: table-row;  /* height is dynamic, and will expand... */
    height: 100%;        /* ...as content is added (won't scroll) */
    background: turquoise;
}
.footer {
    display: table-row;
    background: lightgray;
}
<div class="wrapper">
    <div class="header">
        <h1>Header</h1>
        <p>Header of variable height</p>
    </div>
    <div class="content">
        <h2>Content that expands in height dynamically to adjust for new content</h2>
        Content height will initially be the remaining
        height in its container (<code>.wrapper</code>).
        <!-- p style="font-size: 4000%">Tall content</p -->
    </div>
    <div class="footer">
        <h3>Sticky footer</h3>
        <p>Footer of variable height</p>
    </div>
</div>

C'est ça. Les divs sont emballées comme vous vous en doutez.

81
Dan Dascalescu