0

I'm trying to get a group of div's (with initial widths) to stretch across a container, expanding their widths when needed. This works great using display:flex, however if it wraps onto a new line, I don't want the items on the new line to stretch if there is any remaining space. I want the new line items to keep the same widths as the other elements in the container.

For example, in this code:

.container
{
 display:flex;
 flex-wrap:wrap;
}

.container > div
{
 width:100px;
    height:100px;
    border:1px #fff solid;
    text-align:center;
    font-size:2em;
    background:#66f;

 flex-grow:1;
}
<!DOCTYPE html>
<html>
<body>

  <div class="container">
    <div>1</div>
    <div>2</div>
    <div>3</div>  
    <div>4</div>
    <div>5</div>
  </div>

</body>
</html>

JSFiddle link, if required: https://jsfiddle.net/xodzL4b9/

If you resize the window, 5 will eventually wrap to the new line but grow to the entire row width. I want it to be on the new line but maintain the width that flex calculated for all of the elements on the first line.

Is that possible to do with Flex (or CSS in general) or will I need to use Javascript?

It's worth noting that I don't know how many elements will be on each line, so I cannot specify a percentage as the width. This is for a responsive layout where I don't want gaps on either side of the container.

EDIT:

Image for clarification

  • The "GAP = BAD" images are what I don't want. This is easily achieved with display:inline-block.

  • The top right image uses display:flex and is good, except for box 25 being stretched to 100% of the screen. I don't want this.

  • The bottom 2 images show exactly what I want. Regardless of resolution (and without using a lot of media queries to support every resolution), the boxes stretch to fill the gaps and are always the same width. No percentage widths are used since a small resolution would use different percentages to a large resolution.

Phil
  • 2,008
  • 1
  • 17
  • 23

2 Answers2

1

You can achieve this using CSS-grid:

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}

.container>div {
  height: 100px;
  border: 1px #fff solid;
  text-align: center;
  font-size: 2em;
  background: #66f;
}
<div class="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Based on what I'm reading about grid, it might work, but its browser compatibility is terrible: https://caniuse.com/#feat=css-grid . The couple of polyfills that I can find are very out of date and don't look like they'll be updated anytime soon :( – Phil May 11 '18 at 16:33
  • @Phil well, grid is only terrible for IE ;) so without IE it's well supported – Temani Afif May 11 '18 at 18:47
  • I just finished testing on A LOT of desktop browsers and phones via BrowserStack. Support for Grid is pretty bad unless the computers/devices are always kept up to date. Looking at the stats for my site, that's not always the case. That said, having a fallback to inline-block if the browser does not support grid seems like the only thing I can do (without implementing in Javascript), so I'll accept your answer as its the best solution at this point in time. – Phil May 11 '18 at 19:59
0

You can just set the width of the items with a %. Then remove the flex grow.

.container > div {
  width:25%;
  height:100px;
  outline:1px #fff solid;
  text-align:center;
  font-size:2em;
  background:#66f;
}

You will also need to change border to outline since border will push the elements 1px on each side. Change border to outline and it will create the 'border' inside the element.

Now if you want to fit let's say 10 elements in one row I would create a media query such as this to allow more elements per row.

@media screen and (min-width:768px) {
  .container > div{
    width:20%;
  }
}
TeoAlmonte
  • 107
  • 1
  • 7
  • As I said in my post, I can't use percentages since I may have 1 element, or 50. If I were to say 20%, then I can fit 5 elements, which may look more stretched than they should on large resolutions, or too squashed on small resolutions. It's too restrictive. Flex solves this by allowing me to keep each element looking as it should, but also catering for all resolutions. – Phil May 11 '18 at 03:44
  • You can use a media query to allow more elements per line, that should work. – TeoAlmonte May 11 '18 at 04:06
  • I could, but that would be a lot of media queries. It shouldn't have to be as difficult as that. TBH, I'd rather use Javascript over having media queries for so many cases. – Phil May 11 '18 at 04:32
  • You should think of the logic behind what you are trying to do. There has to be some sort of rule that triggers the next element moving onto the next row. You can do this mathematically with some algorithm. Maybe try to make your idea more clear. – TeoAlmonte May 11 '18 at 08:26
  • I've edited my original post with an image explaining what I do and don't want. Refer to the text underneath the link explaining things a little more. – Phil May 11 '18 at 16:24