16

Hey I am trying to create a responsive box layout for a gallery, which looks like this http://webdesignerwall.com/demo/responsive-column-grid/

The problem with the example is that the widths are hardcoded and media queries are necessary. I have way to many columns for that to be a feasible solution.

I can achieve the same result with Flex girds, however the last column is larger than the others as shown in this CodePen:

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

HTML

<div class="flex-container same-width same-height">
  <div class="flex-item">
    <div>g</div>
  </div>
  <div class="flex-item">
    <div>g</div>
  </div>
  <div class="flex-item">
    <div>g</div>
  </div>
  <div class="flex-item">
    <div>why am I longer than my friends?</div>
  </div>
</div>

CSS

.flex-container {
    display: -webkit-flex;
    display: flex;
    width: 100%;
    max-width: 950px;
    flex-wrap: wrap;
    justify-content: space-between;
    background: grey;

  & > * {
    min-width: 300px;
    background: green;
    max-width: 404px;
    flex: 1 1 auto;
  }
  .flex-item > div {
    background: red;
  }
}

Question: How can I make the last column the same size as the others?

Paul
  • 1,190
  • 3
  • 12
  • 24
  • Hey guys I just found this [link](http://codepen.io/dalgard/pen/Dbnus), which solves the problem beautifully. Unfortunately the compatibility isn't too great atm. IE10 isn't working. Latest chrome and opera are fine. – Paul Feb 27 '14 at 03:16
  • All you need is a preprocessor mixin, and a single line of code to use that mixin. See here: http://stackoverflow.com/a/36401995/635069 – Merott May 04 '16 at 09:32

4 Answers4

31

Set the flex grow to 0.

fiddle: http://jsfiddle.net/RichAyotte/Ev5V7/

enter image description here

<div class='flex-container seven'>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
</div>

.flex-container {
    display: flex;
    flex-flow: row wrap;
    justify-content: flex-start;
}
.flex-container div {
    font-size: 200%;
    padding: 2mm;
    margin: 10px 10px;
    flex: 0 1 20%;
    box-shadow: 3px 3px 2px 0px rgba(50, 50, 50, 0.5);
}
Richard Ayotte
  • 5,021
  • 1
  • 36
  • 34
  • My initial reaction is quite impressed. Will play with it tomorrow and get back to you. Cheers. – Paul Mar 24 '14 at 12:02
11

It's a common misconception, but Flexbox is not a grid system. Once the flex items are set to be flexible, they can only be sized relative to the other flex items on the same line, not with the flex items on any other line. There is no way to force them to line up without using a specific width (though this width can be a percentage).

Your min-width serves no purpose here since your flex items are flexible. Your flex-shrink value serves no purpose because your flex items are allowed to wrap. The max-width is the only thing preventing the items on the last line from filling the entire row. You would have to know the exact width of the items in the preceding row in order to set the correct max-width value.

Related:

Community
  • 1
  • 1
cimmanon
  • 67,211
  • 17
  • 165
  • 171
  • Yes you are right. Flexbox isn't really designed to do that at this point. I really wish you could do that though, as it is so close to being the perfect solution to the problem I have stated in the original question. Thanks for your help. Would love to upvote your answer, however I don't have enough reputation yet :) – Paul Oct 29 '13 at 06:01
4

Using a flex box you have to be careful about your max- and min- widths. Quoting from w3schools:

Tip: Elements that are flexible can shrink or grow as the box shrinks and grows. Whenever there is extra space in a box, flexible elements are expanded to fill that space.

To counteract this, initiate a width of X number pixels for your container but use percentages instead of your pixel amounts for the interior boxes. The percentage of the container will be the same for all your columns.

Doing this also removes the need for a flex box because those are only if you want expansion of the boxes in the horizontal direction (making them wider based on content of each one) rather than vertical direction.

PS - if you want this responsive and to keep the widths proportional to the space in between as well, use percentages for your margins as well (but keep in mind border and padding sizes). This isn't necessary but is a useful feature for keeping a consistent look and feel on different devices.

Deryck
  • 7,608
  • 2
  • 24
  • 43
  • Thanks for talking your time to answer. Unfortunately I don't quite understand what you mean. Following you instructions that's all I can get: [codepen](http://codepen.io/anon/pen/doLhr), which doens't really solve my problem – Paul Oct 28 '13 at 02:10
  • Here is what I see in that codepen: http://i.imgur.com/Wvzosh1.jpg - that's with Google Chrome latest but also Firefox latest shows the same. The one that says "why am i longer..." is the same size as the others. Can you send a screenshot of what you're seeing or if this isn't what you want, I apologize and would love to revisit this with more detail if you can provide it. – Deryck Oct 28 '13 at 22:35
  • Yep I see exactly the same as you Sir. Also using the latest Chrome. I guess what I am looking for is a grid like in that codepen, however responsive in the way that the containers will fill up to use the remaining space. Seeing that Firefox doesn't even support the flex-warp attribute yet, this is definitely the wrong way to go about it. I think I might have to stick with media-queries for this task. Thanks for your help. – Paul Oct 29 '13 at 05:58
  • Please don't quote w3school.... There are many errors in their documentation, their name suggest they affiliated to W3C (open source/standards) but they are profit, they are VERY often out of date, and many superior sources exist... – Romain Bruckert Jun 16 '17 at 07:54
4

CSS

.box {
    display: grid;
    grid-template-columns: repeat(auto-fill,minmax(160px, 1fr));
}

HTML

<div class="box">
    <div>One</div>
    <div>Two</div>
    <div>Three</div>
    <div>Four</div>
    <div>Five</div>
    <div>Six</div>
    <div>Seven</div>
    <div>Eight</div>
    <div>Nine</div>
    <div>Ten</div>
</div>