1

I am trying to create a dynamic grid which contains tiles - there is one row and the grid columns have a % width.

At larger resolutions, the width might be 30% but at lower resolutions it might be 50% or even 100% - they are all floated left and this works fine for widths.

The issue is when one of the columns has more content than the others hence is taller and it messes up the grid system and user could end up with row of 3 then row of 1 then row of 2.

I can't use min/max height in CSS as, depending on the user, the div might have 10 words or 1000 words. The "row" is actually a wrapper div as it incorporates multiple "rows" so setting a height on that doesn't work either.

How can I create a dynamic responsive fluid grid layout using something like the below where all widths are the same and all heights are the same as the highest box - I don't mind using JS/jQuery if it is needed which I suspect it will be.

<div id="row">
    <div class="col">COL1</div>
    <div class="col">COL2 Text added to this column so height is different</div>
    <div class="col">COL3</div>
    <div class="col">COL4</div>
    <div class="col">COL5</div>
    <div class="col">COL6</div>
</div>

#row {
    float:left;
    border:1px solid red;
}

.col { float:left;
width:30%; border:1px solid black; margin:1%;}

@media screen and (max-width: 400px) {
    .col {width:45%;}
}

http://jsfiddle.net/8bnqbpnr/

bhttoan
  • 2,641
  • 5
  • 42
  • 71

3 Answers3

2

You could use the :nth-child pseudo-selector to force clear:left on specific columns and media queries for responsiveness: http://jsfiddle.net/mpartarrieu/109gjy37/

<div id="row">
    <div class="col">COL1</div>
    <div class="col">COL2 Text added to this column so height is different</div>
    <div class="col">COL3</div>
    <div class="col">COL4</div>
    <div class="col">COL5</div>
    <div class="col">COL6</div>
    <div class="col">COL7</div>
    <div class="col">COL8</div>
    <div class="col">COL9</div>
    <div class="col">COL10</div>
    <div class="col">COL11</div>
    <div class="col">COL12</div>
    <div class="col">COL13</div>
</div>

#row {
    float:left;
    border:1px solid red;
}

.col { float:left;
width:30%; border:1px solid black; margin:1%;}

@media screen and (min-width: 401px) {
    #row .col:nth-child(3n+1) {  
        clear: left;
    }
}

@media screen and (max-width: 400px) {
    .col {width:45%;}
    #row .col:nth-child(2n+1) {  
        clear: left;
    }

}
  • Maybe one should mention that if you have more then 1 breakpoint, you would need to explicitly write something like `@media screen and (max-width: ...) and (min-width:..)` because otherwise you add multiple child rules. – Adam Feb 20 '16 at 10:29
2

You can fix this using flexbox. I'm quite fond of flexbox myself :) Just remember, if your target audience will use IE8 or older, that you can't use this.

.container {
  width: 400px;
  margin: 32px auto;
}
.row {
  border: 1px solid red;
  display: flex;
  width: 400px;
  flex-wrap: wrap;
  justify-content: space-between;
}
.col {
  box-sizing: border-box;
  padding: 10px;
  border: 1px solid black;
  margin: 5px;
  width: 30%;
}
<div class="container">
  <div class="row">
    <div class="col">COL1</div>
    <div class="col">COL2 Text added to this column so height is different</div>
    <div class="col">COL3</div>
    <div class="col">COL4</div>
    <div class="col">COL5</div>
    <div class="col">COL6</div>
  </div>
</div>
Pjetr
  • 1,372
  • 10
  • 20
  • That looks really useful, for those using IE7 and before - I assume they will just see the current layout which works but breaks in certain mixed height situations or will it be uber messed up for them? – bhttoan Aug 14 '15 at 13:08
  • @bhttoan It just wouldn't know what to do and default to `display: block`, so you'll need to write fallback code. This is old, but still a good guide: http://coding.smashingmagazine.com/2013/05/22/centering-elements-with-flexbox/ – Pjetr Aug 14 '15 at 13:27
  • CodePen = 404 :/ – Martin James Dec 22 '18 at 18:36
  • @MartinJames, it was simply copy and pasting of the code above... https://codepen.io/pjetr/pen/bOzyJv here you go – Pjetr Jan 15 '19 at 11:28
0

There is a simple solution for this which even works for IE 6. All you need to do is to replace float:left to display:inline-block. Here is a jFiddle. However, there are 2 things to mention:

  1. Make it work for IE6 The display:inline-block property only works for inline elements. Thus instead of div you may want to use a span element if you want to support IE 6.

  2. Delete Whitespaces Since your elements are now inline, the whitespace between your span's are displayed. To remove them and keep a clean code you could write it like that:

    <span class="col">COL1</spanasd><!-- remove whitespace --><span class="col">...</span>

Maybe interesting to read: Advantages of using display:inline-block vs float:left in CSS.

Community
  • 1
  • 1
Adam
  • 25,960
  • 22
  • 158
  • 247