I'm trying to make kind of masonry layout of items using display: flex;
It's running good until my items has different sizes:
here is example: http://jsfiddle.net/2pL3j07x/1/
I want small items below big items to wrap it around (2 items in a 'row' below big item should easly fit but only 1 goes there)
Is it possible with css flex to do so?
CSS masonry with flexbox, :nth-child(), and order. On the surface it seems fairly easy to create a masonry layout with flexbox; all you need to do is set flex-flow to column wrap and voilà, you have a masonry layout.
To use masonry layout, one of your grid axes needs to have the value masonry . This will then be referred to as the masonry axis, the other axis will have rows or column tracks defined as normal, this will be the grid axis. The CSS below creates a four-column grid, with the rows set to masonry .
Masonry layout is a layout method where one axis uses a typical strict grid layout, most often columns, and the other a masonry layout. On the masonry axis, rather than sticking to a strict grid with gaps being left after shorter items, the items in the following row rise up to completely fill the gaps.
I know you don't want to use transforms, but this works exactly as described and actually has better browser support than flexbox does (although as far as the regularly updating browsers that's a less compelling argument than normal).
Regardless:
What we're doing here:
.flex-c {
transform: rotate(90deg) scaleY(-1);
transform-origin: left top;
}
Setting the direction – We're twisting it to go up to down by moving the left side of the container to the top, a one-quarter turn clockwise.
Flipping the whole she-bang – We're flipping the container on the Y-axis, so that the orientation is correct (apparent as ltr
in this case)
.flex-c:after {
content: '';
display: table;
clear: both;
}
Fixing the float clearing stuff – Good resource on that here
.flex-i {
transform: rotate(90deg) scaleY(-1);
height: 100px;
width: 100px;
background-color: gray;
margin: 0 10px 10px 0;
float: left;
}
Reverting the flipping and twisting for individual items – We want these to display correctly, so we untwist them with the transform
rule to head the .flex-i
rule.
So let's take a look at what's going on with the final result:
Some downsides:
Hope this helps!
So the comments raised the rather obvious question "What if we want more than one big element in this layout?"
Perfectly reasonable, and the solution as presented is going to leave some rather ugly gaps, granted. Unfortunately, if you need a pure content fill for those, you'll need to get much more creative and use either a JavaScript layout system (boo, slow, nasty, hard-to-maintain) or do something that several other masonry layouts have had to do before: tuckpointing
We're going to shim our empty spaces with dummy items. These can be pre-selected images, tiles, anything that's going to add a splash of flair in place of actual content without distracting from the content.
Here's how we do it:
Fiddle
Update the .flex-c
container to hide its overflow
.flex-c {
transform: rotate(90deg) scaleY(-1);
transform-origin: left top;
overflow: hidden;
}
Add an easily disguised shim pseudo-element
.flex-i:not(.big):after {
content: '';
height: 100px;
width: 100px;
left: 110px;
top: 0;
position: absolute;
background-color: pink;
}
ALTERNATIVELY: You can do this in a way that's less CSS3-fancy but has better support
.flex-i:after {
content: '';
height: 100px;
width: 100px;
left: 110px;
top: 0;
position: absolute;
background-color: pink;
}
.flex-i.big:after {
display: none;
}
What this does in terms of the fiddle is creates a little pink box that pops out of the right side of each one of those content items. If there's a box there already, it gets covered up. If it's missing, we show the dummy box. Super simple.
I think for what you are tryig to do, it would be easier using float:left;
instead of the flex
property. I made an updated
.flex-c {
display: block;
height: 450px;
width: auto;
}
.flex-i {
height: 100px;
width: 100px;
float:left;
background: gray;
margin: 0 10px 10px 0;
}
.big {
width: 210px;
height: 210px;
float:left;
}
.wrap {
display: inline-block;
}
<div class="wrap">
<div class="flex-c">
<div class="flex-i big"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
<div class="flex-i"></div>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With