user2952238
user2952238

Reputation: 787

CSS grid containing divs of different height

I'm trying to get a grid to work as I want to. It contains 2 different sizes of elements and I want it to layout as a masonry but without using any lib, since it's a quite simple layout that I just can't get my head around. You see on the image that the 2 small items jump down as they float. Anyone that can help me here? The grid is gonna be repeatable with this same structure.

Reference image:

grid

.grid {
  width: 100%;
}
.half {
  float: left;
  width: 50%;
  max-width: 1000px;
  border: 1px solid #000000;
}
.forth {
  float: left;
  width: 25%;
  max-width: 500px;
  border: 1px solid #000000;
}
<section class="grid">
  <div class="half">
    <img src="http://placehold.it/1000x1000">
  </div>
  <div class="forth">
    <img src="http://placehold.it/500x500">
  </div>
  <div class="forth">
    <img src="http://placehold.it/500x500">
  </div>
  <div class="half">
    <img src="http://placehold.it/1000x1000">
  </div>
  <div class="forth">
    <img src="http://placehold.it/500x500">
  </div>
  <div class="forth">
    <img src="http://placehold.it/500x500">
  </div>
</section>

Upvotes: 4

Views: 13146

Answers (4)

Sam
Sam

Reputation: 755

Harrys answers works really well and if you are using this grid for a whole site it would be the approach I would go for but if you do not wish to further nest the elements perhaps this would be an simpler solution.

Simply move the two div.fourth in front of the first div.half and float them right. Then float the second div.half right and Bob's your uncle.

<section class="grid">
    <div class="forth right">
        <img src="http://placehold.it/500x500?text=block+1">
    </div>
    <div class="forth right">
        <img src="http://placehold.it/500x500?text=block+2">
    </div>  
  <div class="half">
        <img src="http://placehold.it/1000x1000?text=block+3">
    </div>
    <div class="half right">
        <img src="http://placehold.it/1000x1000?text=block+4">
    </div>
    <div class="forth">
        <img src="http://placehold.it/500x500?text=block+5">
    </div>
    <div class="forth">
        <img src="http://placehold.it/500x500?text=block+6">
    </div>
</section>

I would also suggest applying box-sizing: border-box info here

It would also make more sense to apply the max width to the .grid and remove it from it's children & make the img ‘responsive’

// Tidy up demo
// =================================
* {
    box-sizing: border-box;
}
// apply max width to image
img {
    max-width: 100%;
    height: auto;
    display: block;
}
// apply max width to grid container
.grid {
    max-width: 2000px;
    width: 100%;
    overflow: hidden;
    margin: 0 auto;
}
// =================================

// orignal code
// =================================
.grid {
    width: 100%;
}

.half {
    float: left;
    width: 50%;
    max-width: 1000px; // with a max width applied to the grid you don't need these lines
    border: 1px solid #000000;
}

.forth {
    float: left;
    width: 25%;
    max-width: 500px; // with a max width applied to the grid you don't need these lines
    border: 1px solid #000000;
}
// =================================

// bit you need to add
// =================================
.right {
    float: right;
}
// =================================

// just so you can see the difference
// =================================
.right {
    background-color: #3cf;
}
.right img {
    opacity: 0.8;
}
// =================================

Finally my example on codepen http://codepen.io/samwalker/pen/MwpLvM?editors=110

Upvotes: 3

Harry Robbins
Harry Robbins

Reputation: 549

You'll have to nest the grids. Start with two half grids as siblings, next to each other. Then the content you want in the left column needs to go in the first half, including the final 2 quarter grids. Then begin the next half with the top two quarter grids, and place the half content inside it.

<section class="grid">
    <div class="half">
        <span class="contentLg">half A</span>
        <div class="fourth">
            <span class="contentSm">fourth C</span>
        </div>
        <div class="fourth">
            <span class="contentSm">fourth D</span>
        </div>
    </div>
    <div class="half">
        <div class="fourth">
             <span class="contentSm">fourth A</span>
        </div>
        <div class="fourth">
             <span class="contentSm">fourth B</span>
        </div>
        <div class="clear"></div>
        <span class="contentLg">half B</span>
    </div>
</section>

Nesting grids should work fine so long as they don't have default margin. It's better to space the grids out by giving them box-sizing:border-box; padding (which will allow the elements total width to remain unchanged).

If you just add content to go in the half grid that doesn't float, you'll need to clear the float (in my example I used a div with class "clear")

When nesting grids, percentage values will prove troublesome. The simplest way around that is to use pixel widths. Example CSS can be seen at this fiddle.

http://jsfiddle.net/j0c7aL2c/

You have other options with the CSS. You can try and alter the value of nested grids, like below, but this is complicated to maintain and confusing when you're in firebug.

.fourth {width:25%;}
.half .fourth {width:50%}

I'd suggest to go with pixel widths, and use media queries to adjust those pixel widths for a responsive layout. Or adjust the widths given context, but be aware CSS namespaces add specificity and could make overrides to grid containers more challenging.

.half { width:480px;}
/* Tablet - Portrait and Landscape */
@media only screen 
  and (min-device-width: 768px) 
  and (max-device-width: 1024px) 
  and (-webkit-min-device-pixel-ratio: 1) {
    .half { width:240px;}
}

vs.

.half { width:480px;}
.insideMyAwesomeContainer .half { width:240px;}

Upvotes: 0

ric0c
ric0c

Reputation: 33

I would target the bottom right 1000px X 1000px block you have, give it an additional class and give it float:right;

https://jsfiddle.net/fso51v01/

Upvotes: 0

Woodrow Barlow
Woodrow Barlow

Reputation: 9057

To accomplish this without JavaScript, you'll need to think about it in terms of columns. This works when you're just dealing with halves and quarters, but might get complicated / impossible if the content is sized too dynamically. Here is a simplified example (you'll have to play around with margins).

* {
  margin: 0;
  padding: 0;
}
.col, .col div {
  display: inline-block;
}
.col {
  width: 205px;
}
<section class="col">
  <div class="half">
    <img src="http://placehold.it/205x205">
  </div>
  <div class="fourth">
    <img src="http://placehold.it/100x100">
  </div>
  <div class="fourth">
    <img src="http://placehold.it/100x100">
  </div>
</section>
<section class="col">
  <div class="fourth">
    <img src="http://placehold.it/100x100">
  </div>
  <div class="fourth">
    <img src="http://placehold.it/100x100">
  </div>
  <div class="half">
    <img src="http://placehold.it/205x205">
  </div>
</section>

Upvotes: -1

Related Questions