user2339729
user2339729

Reputation: 59

Getting flexbox to flow like bootstrap columns

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?

Upvotes: 1

Views: 2747

Answers (4)

Asons
Asons

Reputation: 87201

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>

Upvotes: 2

user2339729
user2339729

Reputation: 59

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

Upvotes: -1

Michael Benjamin
Michael Benjamin

Reputation: 371331

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?

Upvotes: 1

unpollo
unpollo

Reputation: 804

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

Upvotes: 1

Related Questions