Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Masonry Layout in CSS3?

Tags:

html

css

flexbox

I try to use the following structure to generate the layout described below.

<div class="flexbox">
  <div class="box box1">child 1</div>
  <div class="box box2">child 2</div>
  <div class="box box3">child 3</div>
  <div class="box box4">child 4</div>
</div>

I made an example for that here.

The layout should be as follows:

  • if there is only one box inside the flexbox it should have 50% of the width inside the flexbox (see following figure)

enter image description here

  • if there are two boxes they both should take 50% of the space inside the flexbox

enter image description here

  • if there are three boxes, each box should take 50% of the space, while the first two boxes are in row 1 and the third box appears in row 2

enter image description here

How can I achieve this kind of layout with css?

Edit: The boxes might not have the same height. This means they should fill the remaining space vertically. The width is always the same. See the following image for an example.

enter image description here

Edit: I found a way to make masonry with pure css see here: http://jsfiddle.net/confile/aGXzU/

The problem is that the boxes are in the wrong order. They should be from left to right and from top to bottom like this:

1 2 3
4 5 6 
7 8 9

Is there a way to get this with css and only little javascript?

like image 763
confile Avatar asked Dec 02 '22 17:12

confile


2 Answers

Here is a new answer and hope it solves your problem , following two Fiddles , to handle this issue , the first script will throw all odd children in the left side , and all even children on the right side

side1=0,side2=0

$(".flexbox").children().each(function(index, element) {
    if (index % 2 === 0) //odd children (starts with 0 )
    {
$(this).css("top",side1+"px") 
side1+=parseInt($(this).css("height"))
    }
else //even children
    {
$(this).css("top",side2+"px")
$(this).css("left","50%") 
side2+=parseInt($(this).css("height"))
    }   
});

http://jsfiddle.net/prollygeek/QD9kZ/

while this second fiddle , will balance the two sides based on elements heights so that there is no big deviation in the columns heights all the time , use any script of them it is up to you.

side1=0,side2=0
$(".flexbox").children().each(function(index, element) {
if(side1<=side2)
{
$(this).css("top",side1+"px") 
side1+=parseInt($(this).css("height"))
}
else if(side2<side1)
{
$(this).css("top",side2+"px")
$(this).css("left","50%") 
side2+=parseInt($(this).css("height"))
}

});

http://jsfiddle.net/prollygeek/hP6fS/

like image 158
ProllyGeek Avatar answered Dec 19 '22 00:12

ProllyGeek


Flexbox cannot be used to recreate the Masonry layout. Period.

Flexbox is for controlling how elements flow along either a horizontal row (flex-direction: row, which is the default) or vertical column (flex-direction: column). That means you can only eliminate excess space in one direction: left/right (row) or top/bottom (column). Because flex-direction: column requires an explicit height to enable wrapping, it is entirely unsuitable for this purpose.

The CSS Multi-column Layout Module is the closest you can get to recreating a Masonry layout using pure CSS, but it still only allows you to eliminate excess space between the elements in one direction: vertically. The key difference between this and Flexbox (using the column direction) is that the Multi-Column module does not require an explicit height and will distribute the contents equally between each of the columns as best it can (this can be controlled via the column-fill property). The gap between the columns is controlled by the column-gap property.

http://codepen.io/cimmanon/pen/CcGlE

.my-element {
  -moz-columns: 15em;
  -webkit-columns: 15em;
  columns: 15em;
}
like image 20
cimmanon Avatar answered Dec 18 '22 23:12

cimmanon