tschofen
tschofen

Reputation: 161

Don't stretch one item in CSS Flex box with complex layout

I'm trying to create a nested flex box layout that stretches all columns properly (vertically). It seems to work pretty well, except for stretching of one item inside a the nested layout.

|---------------------------------------------|
|Header                                       |
|---------------------------------------------|
||--------------------------------|----------||
||TITLE IS THE ISSUE!             |Right     ||
||--------------------------------|Aside     ||
||Left    |Content                |          ||
||Aside   |                       |          ||
||        |                       |          ||
||        |                       |          ||
||        |                       |          ||
||--------|-----------------------|----------||
|---------------------------------------------|
|Footer                                       |
|---------------------------------------------|

The problem I'm having is that if the Right Aside gets longer than the other content, the Header stretches vertically. If I try to override the Title align-self attribute to stop it from stretching nothing happens.

A plunker that clearly shows the issue. Look at the gray area (Title - must not grow): http://plnkr.co/edit/9VBSOKi0ipAy1QDpNAKb?p=preview

Thanks...

Upvotes: 4

Views: 6860

Answers (1)

misterManSam
misterManSam

Reputation: 24692

From scratch — building the layout from the inside out

There are 3 nested flex containers in this layout.

#1 - The two inner columns

Columns flex parent

These columns are wrapped in their own flex parent called .flex-inner-columns. The <main> element could be a good choice for this parent.

The HTML

<main class="flex-inner-columns">

  <div class="column-left">
    column-left
  </div>

  <div class="column-right">
    column-right
  </div>

</main>

The CSS

.flex-inner-columns {
  display: flex;
}    
.column-left {
  flex: 1;
 }
.column-right {
  flex: 2;
 }

#2 - Adding the title

Title and column flex parent

The title and the inner columns parent are encased in another flex parent called .flex-inner. The <section> element could be a good choice for this parent.

The HTML

<section class="flex-inner">

  <header class="inner-title">
    <h1>inner-title</h1>
  </header>

  <main class="flex-inner-columns">

    <!-- columns are here -->

  </main>

</section>

The CSS

The flex-direction for this flex parent is set to column. The title is given flex: 0 1 150px and will not grow but will shrink from it's default height of 150px if needed. The columns flex container is given flex: 1 so it will grow and shrink.

.flex-inner {
  display: flex;
  flex: 2;
  flex-direction: column;
}
.inner-title {
  flex: 0 1 150px;
  width: 100%;
}
.flex-inner-columns {
  display: flex;
  flex: 1; /* the inner columns flex parent is now given flex 1*/
}

#3 - The final layout — adding the outer flex parent

Final layout flex outer parent

Everything is wrapped in one final outer container that controls the right aside column. The .flex-inner is given flex: 2 and the .outer-right aside is given flex: 1.

The complete example

body {
  margin: 0;
}
.top-header,
footer {
  height: 10vh;
  background: #E91E63;
}
.flex-outer {
  display: flex;
  height: 80vh;
}
.outer-right {
  flex: 1;
  background: #F48FB1;
}
.flex-inner {
  display: flex;
  flex: 2;
  background: #333;
  flex-direction: column;
}
.inner-title {
  background: #9C27B0;
  flex: 0 1 150px;
  align-self: center;
  width: 100%;
}
.flex-inner-columns {
  display: flex;
  flex: 1;
}
.column-left {
  flex: 1;
  background: #CE93D8;
}
.column-right {
  flex: 2;
  background: #AB47BC;
}
<header class="top-header">Header</header>
<div class="flex-outer">

  <section class="flex-inner">

    <header class="inner-title">
      <h1>inner-title</h1>
    </header>

    <main class="flex-inner-columns">

      <div class="column-left">
        column-left
      </div>

      <div class="column-right">
        column-right
      </div>

    </main>

  </section>


  <aside class="outer-right">
    right outer
  </aside>

</div>

<footer>Footer</footer>

Upvotes: 14

Related Questions