9

I'm looking for cards that have dynamic width to fill their container, yet be able to wrap if the card gets too small. I got it to do that. Yet I notice that the last card fills up the space that's left. I don't want it to do that. I want it to keep the same column structure. is this possible? I don't have to use flexboxes if there's another way to do it let me know.

enter image description here

enter image description here

.container {
    padding: 20px;
    display : flex;
   flex-flow: row wrap;
   background:white;
}
.container > div {
    border: 1px solid black;
    background: #ececec;
    margin:5px;
    min-width:200px;
    padding: 10px;
    margin-left: 10px;
    flex: 1;
}
<div class="container">
    <div>Div 1</div>
    <div>Div 2</div>
    <div>Div 3</div>
    <div>Div 4</div>
</div>

Here's my JSFiddle which is presently doing what the first picture is showing (which is not what I want). Is there a way to do this?

https://jsfiddle.net/foreyez/0b5dm2t2/

TylerH
  • 20,799
  • 66
  • 75
  • 101
Shai UI
  • 50,568
  • 73
  • 204
  • 309
  • https://jsfiddle.net/0b5dm2t2/7/ – connexo Jan 02 '18 at 17:16
  • thanks @connexo but now the cards are not dynamic width (they do not fill container). – Shai UI Jan 02 '18 at 17:18
  • https://jsfiddle.net/0b5dm2t2/12/ – connexo Jan 02 '18 at 17:22
  • Not with flexbox, but CSS grid can do this for you easily. – Adam Jenkins Jan 02 '18 at 17:24
  • @Adam unfortunately the css grid isn't supported in the browser I am using. – Shai UI Jan 02 '18 at 17:26
  • @foreyez - what browser is that? The only mainstream browser that doesn't support CSS grid is <= IE 10 and Opera Mobile/Mini. https://css-tricks.com/snippets/css/complete-guide-grid/#prop-grid-template-areas – Adam Jenkins Jan 02 '18 at 17:28
  • @Adam long story.. but it's a c# web browser control. I need to upgrade it to get the css grid features. – Shai UI Jan 02 '18 at 17:29
  • @Adam actually IE11 has limited support for CSS Grid, too. – TylerH Jan 02 '18 at 17:31
  • @foreyez - the short answer is no, what you are looking to do cannot be achieved with flexbox (without mucking with dummy div's) like another answer suggests. – Adam Jenkins Jan 02 '18 at 17:31
  • Added a new answer that probably is exactly what you were looking for. – connexo Jan 02 '18 at 17:50
  • @foreyez Seeing as CSS support is some of an issue with your current browser setup I'll let you review a suggestion before submitting an actual answer. Would [this](https://jsfiddle.net/39c0x91x/) work for you? It's basically a combination of media queries, `nth-child`, `max-width` and `calc()` to set a max width for the last element at certain conditions. – agrm Jan 02 '18 at 17:57
  • @agrm lol that answer is pure hack. :D love it thanks. will probably mark the css-grid as the official answer tho. – Shai UI Jan 02 '18 at 18:15
  • @foreyez It should emulate the grid result Nedad suggested, but with IE10 support. Not sure if I'd call it a hack as selectors and properties are used pretty much as intended, but obviously stretching the rules in a creative direction :o) A fun challenge though! And several good (and different) answers. – agrm Jan 02 '18 at 18:38
  • Hope, my answer might help you. – Bhojendra Rauniyar Jan 02 '18 at 19:33
  • As my answer showed, it is easy to achieve staying in your current flex box solution. – connexo Jan 02 '18 at 20:28

7 Answers7

13

You can do this with CSS grid layout, using grid-template-columns. With minmax(200px, 1fr) you can set min-width of each column to 200px and max-width to one track of grid layout. You also need to use auto-fit to make tracks take full width in case there is available space.

.container {
  padding: 20px;
  display: grid;
  background: white;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

.container > div {
  border: 1px solid black;
  background: #ececec;
  margin: 5px;
  padding: 10px;
  margin-left: 10px;
}
<div class="container">
  <div>Div 1</div>
  <div>Div 2</div>
  <div>Div 3</div>
  <div>Div 4</div>
</div>
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
3

A late answer, but here is another trick using pseudo-element that you make exactly the same as your div and you put at the end by adjusting order.

No need to add extra HTML

No need to use media query

No need to alter your current CSS and flex layout

.container {
  padding: 20px;
  display: flex;
  flex-flow: row wrap;
  background: white;
}

.container>div {
  border: 1px solid black;
  background: #ececec;
  margin: 5px;
  min-width: 200px;
  padding: 10px;
  margin-left: 10px;
  flex: 1;
}

.container:after,
.container:before {
  content: "";
  margin: 5px;
  min-width: 200px;
  padding: 10px;
  margin-left: 10px;
  flex: 1;
  order: 2;
}
<div class="container">
  <div>Div 1</div>
  <div>Div 2</div>
  <div>Div 3</div>
  <div>Div 4</div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
1

If you're determined to use flex (because of some other layout constraints) you could use some amount of "dummy" divs which are invisible: https://jsfiddle.net/0b5dm2t2/11/

<div class="container">
  <div>Div 1</div>
  <div>Div 2</div>
  <div>Div 3</div>
  <div>Div 4</div>
  <div class='dummy'></div>
  <div class='dummy'></div>
  <div class='dummy'></div>
  <div class='dummy'></div>
</div>

Then set .dummy to an opacity of 0

Alternatively a layout using percentages would give you what you want.

dzuc
  • 761
  • 8
  • 12
0

After all good answers, but here is my solution, in this case you can use flex-wrap: wrap; for parent and flex-direction: column; on items. For width, you can use calc() but i suggest you to use @media to keep all items fit on screen

.container {
  padding: 20px;
  background: white;
  display: flex;
  flex-wrap: wrap;
}

.container > div {
  border: 1px solid black;
  background: #ececec;
  margin: 5px;
  width: calc(100% / 4);
  padding: 10px;
  margin-left: 10px;
  flex-direction: column;
}

JSFiddle

Pedram
  • 15,766
  • 10
  • 44
  • 73
0

This should be what you're looking for. Use the flex property to control the grow rate of the divs.

.container {
  padding: 20px;
  display: flex;
  flex-flow: row wrap;
  background: white;
  flex-direction: row;
}

.container>div {
  border: 1px solid black;
  background: #ececec;
  margin: 5px;
  min-width: 200px;
  padding: 10px;
  margin-left: 10px;
  flex: 1 0 0;
}
<div class="container">
  <div>Div 1</div>
  <div>Div 2</div>
  <div>Div 3</div>
  <div>Div 4</div>
</div>
agrm
  • 3,735
  • 4
  • 26
  • 36
0

You need to play with media query:

.container {
    padding: 20px;
    display : flex;
   flex-flow: row wrap;
   background:white;
   justify-content: space-evenly;
}

.container > div {
    border: 1px solid black;
    background: #ececec;
    margin:5px;
    min-width:200px;
    padding: 10px;
    margin-left: 10px;
}
/* only required to left align last item, defaulting to center */
@media ( min-width: 768px ) and ( max-width: 992px ) {
  .container {
    justify-content: flex-start;
  }
}

Please note: I'm not able to set exact query point for you as I'm using jsfiddle window. You might fix it at your own.

https://jsfiddle.net/0sogzyw0/1/

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
-1

You can make use of the neighboring selector + to limit the width of divs that have at least two preceding neighbors:

.container > div + div + div {
  max-width: calc(100% / 3 - 15px);
}

https://jsfiddle.net/0b5dm2t2/20/

connexo
  • 53,704
  • 14
  • 91
  • 128