4

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?

Michael
  • 32,527
  • 49
  • 210
  • 370
  • Given that, in all circumstances, the boxes each occupy 50% of the width of the parent, why are you using flex-boxes when you could simply use `.flexbox .flex {width: 50%; float: left; box-sizing: border-box;}`? – David Thomas Dec 01 '13 at 00:41
  • 1
    Possible duplicate of [Masonry-style Layout ONLY with CSS](http://stackoverflow.com/questions/12117195/masonry-style-layout-only-with-css) – Zach Saucier Sep 01 '16 at 01:53

5 Answers5

6

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/

ProllyGeek
  • 15,517
  • 9
  • 53
  • 72
5

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;
}
cimmanon
  • 67,211
  • 17
  • 165
  • 171
3

If there are only two columns, why not just use floats, alternating left and right floating/clearing for odd and even boxes?

.container {
    background-color: yellow;
    overflow: hidden;
    width: 100%;
}
.box {
    height: 100px;
    width: 50%;
}
.box:nth-child(odd) {
    float:left;
    clear: left;
}
.box:nth-child(even) {
    float:right;
    clear: right;
}
.box1 {
    background-color: lime;
}
.box2 {
    background-color: blue;
    height: 120px;
}
.box3 {
    background-color: red;
    height: 140px;
}
.box4 {
    background-color: green;
}
<div class="container">
    <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>
Ilya Streltsyn
  • 13,076
  • 2
  • 37
  • 57
  • Nice thinking. Wish it could be extended to N columns! – Howard Feb 20 '16 at 10:35
  • 1
    For those who want to try this, this only works if it just so happens that the height of your boxes are configured as such that they would alternate left to right - but if (in this example) child 2 was shorter than child 1, wouldn't work. – Joao Aug 24 '16 at 20:18
2

For boxes of the same size:

If you're using flexbox, you'll want to use flex-direction: row; and flex-wrap: wrap;

I forked your JSFiddle. All flex-box properties I added are prefixed with -webkit- only

References:


For boxes of multiple sizes:

You'll need a 'masonry' layout. This article should help you with this issue. The last section is entitled 'Pure CSS'; if you want to avoid JavaScript plugins, that should be what you want.

Unfortunately, pure CSS is only able to make top-to-bottom left-to-right layouts. For left-to-right top-to-bottom layouts, you'll need JavaScript. Check out the jQuery suggestions in the article above.

If you want to do this with pure JavaScript (without jQuery), check out this masonry library.

Community
  • 1
  • 1
Tyler Eich
  • 4,239
  • 3
  • 21
  • 45
  • What if the boxes do not have the same height? See my question update. – Michael Dec 01 '13 at 02:02
  • That's a little more tricky. I updated my answer, referencing an article from designshack.net. – Tyler Eich Dec 01 '13 at 12:46
  • Please have a look at my last edit. Do you have any idea for that? – Michael Dec 02 '13 at 13:42
  • At this point, it looks like that layout is too complex for CSS alone. jQuery plugins appear to be the only way to get left-to-right, top-to-bottom masonry layouts. – Tyler Eich Dec 02 '13 at 14:18
  • I want to do it without JQuery only JavaScript. – Michael Dec 02 '13 at 14:22
  • Well I know this lib but it is too big. I want to isolate only the layout function and the relayout when I add elements. – Michael Dec 02 '13 at 14:37
  • 1
    To do that, you'd have to dig through the source code and remove all unnecessary code without breaking the library. Can't really help you there :-( – Tyler Eich Dec 02 '13 at 16:35
2
.flexbox {
    background-color: yellow;    
    width: 100%;
    height: 300px;
}
.box {
    float:left;
    position:realtive;    
    height: 100px;
    width:50%;
}

try adding and removing children !!

http://jsfiddle.net/prollygeek/8hHDg/5/

ProllyGeek
  • 15,517
  • 9
  • 53
  • 72