1

I'm trying to make a three column setup with gutters that has equal heights. I'm currently trying to do this with flexbox but the issue I'm having is that if a row ends up having two columns, the justify-content: space-between; makes a gap in the middle instead of flowing left to right like bootstrap columns would do. I thought this would be done with align-content: flex-start; but I'm either using it wrong or it doesn't work the way I'm trying to use it. Is there a way to have flexbox use the space between for the gutters but keep the left to right flow? Here is a link to show the issue I'm having and how I want it to look.

http://codepen.io/anon/pen/jWvqdL

Also, is there a way to use flexbox with the padding and column width % setup of bootstrap then have a child element inside the column that is 100% height?

4 Answers4

2

Here is a version that does what you want.

It shows both a 2 and 3 column layout, with just 2 extra CSS rules

.container2,
.container3 {
  max-width: 840px;
  margin: 0 auto;
  border-right: 1px solid red;
  border-left: 1px solid red;
}
.flex {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 40px;
}
.container3 .column {
  box-sizing: border-box;
  margin-bottom: 12px;
  width: calc(33.33% - 8px);
  background: #000;
}
.container3 .column:nth-child(3n+2),
.container3 .column:nth-child(3n+3) {
  margin-left: 12px;
}
.column-content {
  padding: 20px;
  color: #fff;
}

.container2 .column {
  box-sizing: border-box;
  margin-bottom: 12px;
    width: calc(50% - 6px);
  background: #000;
}
.container2 .column:nth-child(2n+2) {
  margin-left: 12px;
}
<div class="container3">
  <div class="flex">
    <div class="column">
      <div class="column-content">
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
      </div>
    </div>
    <div class="column">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
  </div>
</div>

<hr>

<div class="container2">
  <div class="flex">
    <div class="column">
      <div class="column-content">
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
      </div>
    </div>
    <div class="column">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
  </div>
</div>

Update based on comments for mixed columns

    .container {
      max-width: 840px;
      margin: 0 auto;
    }
    .flex {
      display: flex;
      flex-wrap: wrap;
      margin-bottom: 40px;
      margin-left: -12px;
    }
    .column {
      box-sizing: border-box;
      margin-bottom: 12px;
      margin-left: 12px;
      background: #000;
    }
    .column-content {
      padding: 20px;
      color: #fff;
    }

    .col2 {
        width: calc(50% - 12px);
    }
    .col3 {
        width: calc(33.333% - 12px);
    }        
    .col4 {
        width: calc(25% - 12px);
    }
<div class="container">
  <div class="flex">
  
    <div class="column col3">
      <div class="column-content">
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
      </div>
    </div>
    <div class="column col3">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column col3">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>

    <div class="column col2">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column col2">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>

    <div class="column col2">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column col4">
      <div class="column-content">
        <p>Content</p>
      </div>
    </div>
    <div class="column col4">
      <div class="column-content">
        <p>Content</p>
        <p>Content</p>
      </div>
    </div>
    
  </div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
1

One way is by removing justify-content and managing the gutters with margin then using the :nth-child(n) selector to selectively remove the margin so the elements fit. http://codepen.io/anon/pen/QyVEJZ

unpollo
  • 806
  • 5
  • 15
  • Too bad this method doesn't have a nice way to have the columns equal 100% all the way across like bootstrap does. I ever have a little gap at the end of the third one, or it wraps down a line at smaller window sizes. You can see the gap here. http://codepen.io/anon/pen/jWvVZB – user2339729 Feb 03 '16 at 19:52
  • Here's a workaround - http://codepen.io/anon/pen/bExgGW?editors=1100 basically the problem is that without flex, you will never get 3 columns to take up exact 33.3333% increments and not wrap. – unpollo Feb 03 '16 at 20:29
  • (pay special attention to my usage of `.flex:after` to fill the "gap" where there should be a 3rd cell in the bottom row. You might have to add two of these if there will ever only be 1 cell in a row). – unpollo Feb 03 '16 at 20:30
1

One method to solve the problem would be to include a "phantom" div as the last child with visibility: hidden.

I've copied the first flex item from your code and pasted it as the last item in the container. I've added a hidden class to it.

<div class="column hidden">
  <div class="column-content">
    <p>Content</p>
    <p>Content</p>
    <p>Content</p>
  </div>
</div>

Then in your CSS:

.hidden { visibility: hidden; }

Revised Codepen

For other options, see this answer: https://stackoverflow.com/a/34930349/3597276


The reason align-content: flex-start doesn't work as you expect is because the align-* properties work along the cross axis. In this case, as your flex container is flex-direction: row, the cross axis is vertical. So align-content, align-items and align-self would move your flex items up/down, not left right.

For an illustration of main axis / cross axis, and more details about the align-* properties, see here: In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?

Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
-1

This is how I decided to do it. I'm using the standard bootstrap set up, with the padding on columns and negative margin on the parent, but setting display: flex; to the parent and the column with flex-wrap: wrap; on the parent. This way, I can use the boostrap column percent width and have equal height from flex. http://codepen.io/anon/pen/wMExMJ

  • First, only post one answer please. Second, yes, that works good too ... and if I see right, the difference between mine and yours is you use padding/margin to achieve the gutter and I use nth-child/margin .. so it is like tea, some wants lemon, some milk :) – Asons Feb 04 '16 at 15:11
  • And if you limit the width (resize your codepen demo), your gutter collapse, mine doesn't ... here is my [fiddle demo](https://jsfiddle.net/LGSon/s6xqqbgb/1/) if you want to check – Asons Feb 04 '16 at 15:23
  • Ya, I only posted a second answer because it was completely different than when I thought it wouldn't work and I would have to resort to javascript. I guess I should have edited my answer instead. It was your example that gave me the idea of how I ended up doing it. The reason I went with my method instead of yours is because I wanted it dynamic enough to put whatever width column I want and be able to change that column width on responsive without have to do a new nth-child. So, my final code is essentially bootstrap but with equal heights from flexbox. – user2339729 Feb 04 '16 at 15:38
  • 1
    I updated my version for multi columns. ... Also, you didn't ask for a mixed column solution, you asked for a 3 column, which all answers attempt to solve. Adding your own based on some else's, telling it can do mixed columns, IMHO, goes beyond your initial question. Most fair would be to choose the answer that best solve your initial question and ask a new with new requirements (as this already got answers based on your initial request) – Asons Feb 04 '16 at 16:13