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:
- The big item is at the top left.
- Items are displayed in columns.
- The columns are filled from top to bottom.
- The growth is infinitely expansible.
Some downsides:
- Your vertices are flipped for layout on this container. You can mitigate this somewhat by keeping it in a third container for wrap if you don't mind extra markup (I personally do, but to each their own).
- This is going to fail miserably on older browsers – but so is your flexbox solution, so kind of a wash.
Hope this helps!
Edit:
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.