Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested flexbox with scrolling area

Tags:

css

flexbox

I'm trying to achieve this layout in the latest Chrome, Firefox and IE11:

Layout example

I can get this working with the following:

html {
  box-sizing: border-box;
}
*, *:before, *:after { 
  box-sizing: inherit;
}

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

p { line-height: 2em; }

header, footer, article { padding: 10px; }

#parent {
    height: 100%;
    display: flex;
    flex-flow: column nowrap;
    background-color: limegreen;
}

#parent > header {
    flex: none;
    background-color: limegreen;
}

#parent > footer {
    flex: none;
}

#child {
    display: flex;
    flex-direction: column;
    background-color: red;
    height: 100%;
    min-height: 0;
}

#child > header {
    flex: none;
    background-color: #aaa;
}
#child > article {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0px;
}
#child > footer {
    flex: none;
    background-color: #aaa;
}
<section id="parent">
    <header>Parent flex header </header>
    
    <section id="child" >
        <header>Child flex header</header>
        <article>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
        </article>
        <footer>Child flex footer</footer>
    </section>
    
    <footer>Parent flex footer</footer>
</section>

However some of the CSS I find a bit strange and I want to make sure that I have the most chance to not produce CSS that will break in some browser update. The reason for this is that the software will run on actual hardware (kind of like your router admin interface) and cannot be updated as easily as a regular website.

So the CSS that kind of troubles me is the scrollable article:

#child {
    display: flex;
    flex-direction: column;
    background-color: red;
    height: 100%;
    min-height: 0;
}

I fiddled around with the height and min-height to make it work in all three. Originally I had height: 100% only, but that didn't work in Firefox. Specifying min-height: 0 would work in Chrome and FF, but not in IE. The combination seemed to satisfy all 3, but who is correct? Can I be reasonably sure that this wont break in the next FF or Chrome? Does this code make sense from a 'spec-perspective'?

like image 409
Auke Avatar asked Apr 03 '15 10:04

Auke


2 Answers

Setting min-height is indeed required, and the correct way to achieve the desired layout. From the spec:

By default, flex items won’t shrink below their minimum content size (the length of the longest word or fixed-size element). To change this, set the min-width or min-height property.

So only by setting min-height do you allow your your <article> to actually make use of flex-shrink and fit into the parent flex container.

If I see this correctly, the issue you see with IE matches the bug described here and acknowledged here:

In IE 10-11, min-height declarations on flex containers in the column direction work to size the containers themselves, but their flex item children do not seem to know the size of their parents. They act as if no height has been set at all.

This might (or might not) encompass issues regarding overflow.

like image 164
janfoeh Avatar answered Oct 20 '22 22:10

janfoeh


Alternative answer: just specify flex:1 which was missing from #child. This implicitly sets flex: 1 1 0, i.e. the third 0 means flex-basis:0. This matters because the default initial value of flex-basis is not 0 but auto, which in turn effectively means content-sized.

From the spec:

[The third component in flex] sets the flex-basis longhand and specifies the flex basis: the initial main size of the flex item, before free space is distributed according to the flex factors. It takes the same values as the width property (except auto is treated differently) and an additional content keyword. When omitted from the flex shorthand, its specified value is 0%.

If the specified flex-basis is auto, the used flex basis is the computed value of the flex item’s main size property. If that value is itself auto, then the used flex basis is automatically-determined based on its content (i.e. sized as for content).

Here is the modified snippet:

html {
  box-sizing: border-box;
}
*, *:before, *:after { 
  box-sizing: inherit;
}

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

p { line-height: 2em; }

header, footer, article { padding: 10px; }

#parent {
    height: 100%;
    display: flex;
    flex-flow: column nowrap;
    background-color: limegreen;
}

#parent > header {
    flex: none;
    background-color: limegreen;
}

#parent > footer {
    flex: none;
}

#child {
    display: flex;
    flex-direction: column;
    background-color: red;
    height: 100%;
    flex: 1;
}

#child > header {
    flex: none;
    background-color: #aaa;
}
#child > article {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0px;
}
#child > footer {
    flex: none;
    background-color: #aaa;
}
<section id="parent">
    <header>Parent flex header </header>
    
    <section id="child" >
        <header>Child flex header</header>
        <article>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
            <p>Lots of content.</p>
        </article>
        <footer>Child flex footer</footer>
    </section>
    
    <footer>Parent flex footer</footer>
</section>
like image 20
Yang Avatar answered Oct 21 '22 00:10

Yang