This is an increasingly common layout that can be relatively easily achieved using flexbox and some clever container markup.
A common problem with tiled layouts is maintaining consistent spacing and alignment between tiles of differing sizes across multiple rows. Assuming we would like a 30px
margin separating all tiles, we could simply set margin-right: 30px
on all tiles and then use an nth-of-type selector to remove the margin-right
of the last tile in the row.
However, this isn't possible when the relative sizes and order of the tiles is unknown. For example, a two-thirds tile next to a one-third tile won't conform to the same nth-of-type selector rule required to remove the margin of the last tile as a row consisting of three one-third tiles.
A clever way around this is to instead absord the right-most tile's margin into the width of the parent container. We can do with by setting the outer-most div's width to the desired width (in this case 90%) with overflow: hidden
, and then set the inner-container's width to be 100% plus the width of the tile margin; width: calc(100% + 30px)
. This way, no matter what tile is in the right-most position of the row, the tile will sit flush with the edge of its container.
To ensure that the tiles then always fit as desired, we set their flex-basis to be the proportion of the row width we'd like them to occupy minus the tile margin; .third { flex: 0 0 calc(33.33% - 30px); /* for a 1/3 tile */}
Like so:
* {
box-sizing: border-box;
}
.tile-wrapper {
display: block;
position: relative;
width: 90%;
margin: 0 auto;
overflow: hidden;
}
.tile-container {
display: flex;
position: relative;
width: calc(100% + 30px);
flex-wrap: wrap;
}
.tile {
display: inline-block;
margin-right: 30px;
margin-bottom: 30px;
min-height: 200px;
line-height: 199px;
text-align: center;
border: 1px solid black;
}
.two-thirds {
flex: 0 0 calc(66.66% - 30px);
}
.third {
flex: 0 0 calc(33.33% - 30px);
}
.sixth {
flex: 0 0 calc(16.66% - 30px);
}
<div class="tile-wrapper">
<div class="tile-container">
<div class="tile third">1/3</div>
<div class="tile third">1/3</div>
<div class="tile third">1/3</div>
<div class="tile two-thirds">2/3</div>
<div class="tile third">1/3</div>
<div class="tile sixth">1/6</div>
<div class="tile sixth">1/6</div>
<div class="tile third">1/3</div>
<div class="tile sixth">1/6</div>
<div class="tile sixth">1/6</div>
</div>
</div>
Here's a Fiddle
NOTE: This will only work in modern browsers (Chrome, Safari, FF, IE11+). There's also a known bug in IE11 that requires you to use the long-hand flex-basis
style attribute in order to set it to a calc()
value.