2016-05-04 11 views
2

Ich versuche, ein Layout zu erreichen, das sich ausdehnt, um den Bildschirm zu füllen, aber dann scrollt, wenn der Inhalt größer ist als der verfügbare Bereich.Flexbox mit einem scrollbaren Panel

Ich habe eine grundlegende flexbox Ansatz basierend auf this answer, und es macht einen guten Job füllt den Bildschirm, aber überfüllter Inhalt bewirkt, dass der gesamte Bildschirm statt nur einen eigenen Container scrollen.

Wenn ich die Höhe .outer auf einen literalen Wert wie 200px ändern, dann bekomme ich das Bildlaufverhalten, das ich will, aber der untere Inhaltsbereich füllt nicht mehr den Bildschirm.

Ich habe versucht, display: table und verwandte CSS anstelle von Flexbox, aber endete mit dem gleichen Ergebnis.

Ich habe auch mit calc auf der Höhe des Inhaltsfenster betrachtet - so etwas wie

height: calc(100% - 60px); 

aber ich möchte, dass die Header der Lage sein, mit seinem Inhalt zu wachsen, so habe ich nicht einen harten Wert für seine Höhe für die Berechnung.

Ich bin hier auf der Suche nach einer reinen CSS-Lösung statt Fenstergröße mit Javascript von etwas Geschmack.

html, 
 
body { 
 
    height: 100%; 
 
    margin: 0 
 
} 
 
.box { 
 
    display: flex; 
 
    flex-flow: column; 
 
    height: 100%; 
 
} 
 
.box .row { 
 
    border: 1px dotted grey; 
 
    flex: 1 1 auto; 
 
} 
 
.box .row.header { 
 
    background: aliceblue; 
 
} 
 
.box .row.content { 
 
    background: pink; 
 
} 
 
.box .row.content .title { 
 
    height: 40px; 
 
    background: yellow; 
 
} 
 
.outer { 
 
    height: -webkit-calc(100% - 40px); 
 
    height: -moz-calc(100% - 40px); 
 
    height: -o-calc(100% - 40px); 
 
    height: calc(100% - 40px); 
 
    overflow-y: auto; 
 
} 
 
.inner { 
 
    height: 100%; 
 
} 
 
.text { 
 
    height: 100px; 
 
    margin-top: 10px; 
 
    border: 1px solid gold; 
 
}
<div class="box"> 
 
    <div class="row header"> 
 
    <p><b>header</b> 
 
     <br /> 
 
     <br />(sized to content)</p> 
 
    </div> 
 
    <div class="row content"> 
 
    <div class="title"> 
 
     <b>content</b> 
 
     (fills remaining space) 
 
    </div> 
 
    <div class="outer"> 
 
     <div class="inner"> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     </div><!-- inner --> 
 
    </div><!-- outer --> 
 
    </div> 
 
</div>

Antwort

3

Hoffnung das ist das Verhalten, das Sie erwartet.

html, 
 
body { 
 
    height: 100%; 
 
    widht: 100%; 
 
} 
 

 
body { 
 
    margin: 0; 
 
    padding: 0; 
 
} 
 

 
.box { 
 
    display: flex; 
 
    flex-flow: column; 
 
    flex-wrap: nowrap; 
 
    height: 100%; 
 
} 
 
.box .row { 
 
    border: 1px dotted grey; 
 
    flex: 0 0 auto; 
 
    overflow: auto; 
 
} 
 
.box .row.header { 
 
    background: aliceblue; 
 
} 
 
.box .row.content { 
 
    flex: 1 1 auto; 
 
    display: flex; 
 
    flex-flow: column; 
 
    flex-wrap: nowrap; 
 
    background: pink; 
 
} 
 
.box .row.content .title { 
 
    height: 40px; 
 
    background: yellow; 
 
    flex: 0 0 auto; 
 
} 
 
.text { 
 
    height: 100px; 
 
    margin-top: 10px; 
 
    border: 1px solid gold; 
 
} 
 
.outer { 
 
    height: 100%; 
 
    flex: 1 1 auto; 
 
    overflow-y: auto; 
 
} 
 
.inner { 
 
    height: 100%; 
 
}
<div class="box"> 
 
    <div class="row header"> 
 
    <p><b>header</b> 
 
     <br /> 
 
     <br />(sized to content)</p> 
 
    </div> 
 
    <div class="row content"> 
 
    <div class="title"> 
 
     <b>content</b> 
 
     (fills remaining space) 
 
    </div> 
 

 
    <div class="outer"> 
 

 
     <div class="inner"> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
     <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 

 
     </div> 
 
     <!-- inner --> 
 

 
    </div> 
 
    <!-- outer --> 
 

 

 
    </div> 
 
</div>

+0

Hmmm ... näher, aber ich bin nur für den rosaen Teil suche scrollbaren zu sein. Könnten Sie auch speziell auf die von Ihnen vorgenommenen Änderungen hinweisen? – Danny

+0

Ok aktualisiert das Snippet bei meiner Antwort. Bitte testen Sie es. –

+0

Sieht aus wie die neue Version den Trick macht. Gekocht, sieht es wie ein Flex-in-a-Flex aus? – Danny

1

Der Schlüssel zu diesem Layout ist das Erkennen einer Flex-Stück Mindestgröße:

4.5. Implied Minimum Size of Flex Items

Um eine angemessene Standardmindestgröße für Flex-Elemente zu bieten , diese Spezifikation führt eine neueeinWert als Anfangswert von die in CSS 2.1 definierten Eigenschaften min-width und min-height.

Mit anderen Worten, ein Flex-Element wird standardmäßig nie kleiner als die Größe seines Inhalts sein.

Anfangseinstellungen auf einem flexiblen Element:

min-width: auto; 
min-height: auto; 

Dies hat das Potenzial, Produkte zu zwingen, ihre Behälter überläuft.

Die Lösung besteht darin, min-width: 0 für horizontales Scrollen und min-height: 0 für vertikales Scrollen auf dem Flex-Container anzuwenden.

Im Folgenden finden Sie eine vereinfachte Demonstration Ihren Code (JS nur die .text Elemente zu wiederholen ist):

function multiplyNode(node, count, deep) { 
 
    for (var i = 0, copy; i < count - 1; i++) { 
 
     copy = node.cloneNode(deep); 
 
     node.parentNode.insertBefore(copy, node); 
 
    } 
 
} 
 

 
multiplyNode(document.querySelector('.text'), 10, true);
* { box-sizing: border-box; } 
 

 
html, body { 
 
    height: 100%; 
 
    margin: 0; 
 
    border: 1px solid black; 
 
} 
 

 
.box { 
 
    display: flex; 
 
    flex-flow: column; 
 
    height: 100%; 
 
} 
 

 
.header { 
 
    background-color: aqua; 
 
    flex: 0 0 auto; 
 
} 
 

 
.content { 
 
    background-color: yellow; 
 
    flex: 1; 
 
    display: flex;    /* new */ 
 
    flex-direction: column;  /* new */ 
 
    min-height: 0;    /* new; allow flex item to be smaller than its content, 
 
            enabling scroll */ 
 
} 
 

 
.outer { 
 
    background-color: pink; 
 
    flex: 1; 
 
    overflow-y: auto; 
 
} 
 

 
.text { 
 
    height: 100px; 
 
    margin-top: 10px; 
 
    border: 1px solid gold; 
 
}
<div class="box"> 
 
    <div class="header">header (sized to content, i.e., height: auto;)</div> 
 
    <div class="content">content (fills remaining space, i.e. flex: 1;) 
 
      <div class="outer"> 
 
       <div class="inner"> 
 
        <div class="text">Bacon ipsum dolor amet tongue corned beef landjaeger sausage beef meatball, kielbasa pastrami turkey boudin hamburger ham hock chuck tail pork. Shankle tail cupim ribeye.</div> 
 
        </div><!-- inner --> 
 
      </div><!-- outer --> 
 
    </div><!-- content --> 
 
</div><!-- box -->

Getestet auf Chrome, FF und IE11.

Weitere Informationen:

+0

Ich verstehe deinen Punkt, aber wenn ich die 'min-height' von deinem Snippet entferne, funktioniert das Layout immer noch, selbst bei Auto. Umgekehrt, wenn ich die Min-Höhe zu * my * Version hinzufüge, wo die Unterelemente von .content normale divs sind, behebt es es nicht, bis ich '.content' benutze sein eigenes Flex-Layout. Das scheint der entscheidende Faktor für die Höhe der unteren Scheibe zu sein. – Danny

+0

Ja, ich würde vorschlagen, '.content' zu einem verschachtelten Flex-Container in Spaltenrichtung zu machen, damit dieses Layout funktioniert. –

Verwandte Themen