Andreas Argelius
Andreas Argelius

Reputation: 3614

Flexbox column layout that grows with the content

I want to create a layout with three columns using flexbox. The center column should be two items stacked on top of eachother. Like this:

 _______ _______  _______
|       |  top   |       |
| left  |________| right |
|       | bottom |       |
|_______|________|_______|

I'm able to create this for a fixed height flex container but I haven't been able to create it for a dynamic height container.

The HTML structure must be like this. Is it possible to do it with this structure?

<div class="container">
  <div class="left"></div>
  <div class="top"></div>
  <div class="bottom"></div>
  <div class="right"></div>
</div>

This is my attempt with a fixed height. I want it to grow vertically according to the content of the .top and .bottom elements.

.container {
  height: 200px;
  width: 200px;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}
.left,
.center,
.right {
  background-color: rgba(0, 0, 0, 0.5);
}
.left {
  background-color: green;
}
.top {
  background-color: red;
}
.bottom {
  background-color: blue;
}
.right {
  background-color: violet;
}
.top,
.bottom {
  flex: 1 0 50%;
}
.left,
.right {
  flex: 0 1 100%;
}
<div class="container">
  <div class="left">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.</p>
  </div>
  <div class="top">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
  </div>
  <div class="bottom">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
  </div>
  <div class="right">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.</p>
  </div>
</div>

Upvotes: 1

Views: 843

Answers (1)

zer00ne
zer00ne

Reputation: 43870

I wrapped the top and bottom in a flex-direction: column; and made the .container flex-direction: row;. The flow of flexbox always relies on the parent's flex-direction and how that affects it's direct descendants (i.e. children). The way it was originally I don't think it's possible just to have one flex container when you want one group of boxes to flow vertically and the other group of boxes to flow horizontally. One group needs to be isolated from the influence of the flex container or they'll follow suit horizontally if that one container is row or everything will flow vertically if you have only one flex column. There is align-self but it's not going change a flex-items direction, just alignment.

/* Core CSS */

html {
  box-sizing: border-box;
  font: 400 16px/1.45'Source Code Pro';
}
*,
*:before,
*:after {
  box-sizing: inherit;
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
}
body {
  background: #121;
  color: #FEF;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  position: relative;
  width: 100vw;
  height: 100vh;
}
.container {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-content: baseline;
  align-items: baseline;
  overflow-y: auto;
}
.core {
  height: 100%;
  min-height: 200px;
  width: 60%;
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  justify-content: center;
  align-content: space-around;
  align-items: space-around;
}
.left,
.center,
.right {
  background-color: rgba(0, 0, 0, 0.5);
  overflow-y: auto;
}
.left {
  background-color: green;
  width: 20%;
  height: 100%;
}
.top {
  background-color: red;
}
.bottom {
  background-color: blue;
}
.right {
  background-color: violet;
  width: 20%;
  height: 100%;
}
.top,
.bottom {
  flex: 1 1 auto;
}
.left,
.right {
  flex: 1 0 auto;
}
<section class="container">
  <nav class="left">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.</p>
  </nav>
  <main class="core">
    <div class="top">
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
    </div>
    <div class="bottom">
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
    </div>
  </main>
  <aside class="right">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.</p>
  </aside>
</section>

Upvotes: 1

Related Questions