1

I have a dynamic-ish layout with columns, where the number of columns depends on the window width.

Using the image as an example, I have content boxes, which the user can collapse. If the screen was wide enough there would be 3 columns.

Now having a smaller window there's only 2 columns, but when the top left box is collapsed, the box beneath doesn't follow upwards.

I've tried using the column-count CSS propery, but can't make it work. In the specific examples if I have column count 2 it puts 2 boxes in the right column instead of the left.

My example CSS:

#content{
width:100%;;
height:100%;
display:inline-block;
}
#content div{
     border-color:black;
    border-style:solid;
    border-width:2px;
    display:inline-block;
    width:300px;

    vertical-align:top;
}
#box1{
   height:50px; 
}
#box2{
   height:100px;
}
#box3{
   height:30px;
}

Here's a simple jsfiddle of how I'm trying to do it.

http://jsfiddle.net/5cn6ya75/

enter image description here

Are there any CSS properties of html element structures that makes this possible. So far the only solutions i can find either needs me to have a fixed number of columns, or a fixed height on content boxes.

EDIT: In my search for an answer i've come across shapeshifter, which seems to be able to fix my issue, but by using absolute position and then calculate the offset to other element. I'm still very interested in a cleaner css way of creating a dynamic x-column layout, with variable content-box-sizes(collapsable), where elements align topside to the closest element in their column.

1
  • I found your question confusing and not very well explained but Im guessing you mean you want the box that drops down to the next line to sit right under the first box? If so this is not really possible via CSS only. Masonry would be your best option, I have used it before for this type of thing and it great. Commented Jan 28, 2015 at 14:29

5 Answers 5

7
+100

If I've understood your problem correctly, you can absolutely do this without javascript, provided you're targeting modern browsers. As with most complex layouts, the appropriate tool for the job is flexbox.

So here's what I think you're trying to do:

  • if the viewport is sufficiently wide, lay out all boxes in columns
  • if the viewport is not sufficiently wide, lay out boxes vertically, wrapping to as many columns as necessary

If that's correct, the crux of what you need is

@media any and (max-width:[width]) {
  #content {
    display:flex;
    flex-direction: column;
    flex-wrap:wrap;
  }
}

You won't necessarily need rules on the child boxes, but you can manipulate the order in which they appear when "collapsing" other boxes: for example, the following moves #div1 to the end

#content div {
  order:0;
}
#div1 {
  order:1 !important;
}

I've updated your fiddle with the display:flex declaration on #content and some explicit sizes on the children; if you play with those sizes you should be able to get a feel for how it works.

You may need some further tweaks to control whether the child divs expand to fill all available space, and how the columns are spaced.

Sign up to request clarification or add additional context in comments.

1 Comment

Interesting, i'll give this a thourough look when i get the time.
1

I would recommend you to use Masonry.
Its a JavaScript library for cascading grid style layouts like yourse. I'm using it as jQuery Plugin, but you can use it standalone as well.

If you resize the masonary homepage you can see how it works. In addition you have a lot of Options to customize it.


About Shapeshift:

I did't know about shapeshift, but it seems like it would do your Job as well. I think it has a bit too much overhead, because of the Drag&Drop etc. functions you don't Need (And if youre not using JQuery anyway that comes on top)


"Simple" CSS:
Callums Statements are right. The is no automatic way in CSS3. You could use CSS media querys to set some Breakpoints, but it would be really hard work to find the right Breakpoints & Values (I don't think ist worth the time).


As I said (and the other guys before too) there is no clean and "good" CSS Solution and no CSS Grid System yet aswell. The best way is to use a JavaScript libary (with or without JQuery).

3 Comments

i do need drag and drop, but that was already implemented(not by me), i only needed the "float top" because everything else was already implemented. for now shapeshift replaced the existing drag'n drop and it is working, but it feels odd to me that css can't achieve a "float top" like effect.
Ok thats good. I just had the same stuff around wenn I looked for a new design for my Website. I found it really hard to find a good solution, becuse if your really wan't to make it smoth you need JavaScript. It would be great to extend CSS3 with some features for column design.
I'm afraid it is impossible to do without the use of javascript, unless you can live with a vertical masonry layout (top to bottom, then to next column).
1

$( function() {

    $('#container').masonry({
        itemSelector: '.item',
        columnWidth: 70
    });

});
.content{
width:100%;;
height:100%;
display:inline-block;
}
.content div{
     border-color:black;
    border-style:solid;
    border-width:2px;
    display:inline-block;
    width:300px;
    vertical-align:top;
    float: left;
    margin: 5px;
}
#box1{
   height:50px; 
}
#box2{
   height:100px;
}
#box3{
   height:30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://masonry.desandro.com/masonry.pkgd.min.js"></script>

<div id="container" class='content'>
    <div class='item' id="box1"></div>
    <div class='item' id="box2"></div>
    <div class='item' id="box3"></div>
</div>

try it. Live Demo , Demo2

Html

<div id="container" class='content'>
    <div class='item' id="box1"></div>
    <div class='item' id="box2"></div>
    <div class='item' id="box3"></div>
</div>

css

.content{
width:100%;;
height:100%;
display:inline-block;
}
.content div{
     border-color:black;
    border-style:solid;
    border-width:2px;
    display:inline-block;
    width:300px;
    vertical-align:top;
    float: left;
    margin: 5px;
}
#box1{
   height:50px; 
}
#box2{
   height:100px;
}
#box3{
   height:30px;
}

js

$( function() {

    $('#container').masonry({
        itemSelector: '.item',
        columnWidth: 70
    });

});

and add

js in head

http://masonry.desandro.com/masonry.pkgd.min.js

1 Comment

+1, but for the future remember to add a brief, straight to the point explanation of what you are doing / using, instead of raw code with a fiddle. You can (and should) also include the fiddle in the internal StackOverflow fiddler, by pressing CTRL+M or the Code Snippet button (just right the image button). This way if jsFiddle is down, your code will be still visibile in SO
0

Your problem here is that display:inline-block turns each element in the 'row' into a block with the same height as the largest in the row.

Your best options here are to either set a max-height on #content div so that they all appear equal, or to use media queries to display a different grid depending on screen size.

3 Comments

would it be doable if the elements had display:inline; or something else?
There's no automated way at the moment to create a grid like that with generic CSS rules. I would recommend adding something like this instead: @media (max-width: 600px) {#box3{margin-top:-70px;} Changing the breakpoint to match your design. You could also use masonry, a jQuery library which covers what you want to do.
setting a fixed margin top would never work as the boxed are supposed to be collapsable
0

I don't really understand exactly what you are after but if you do set the column width fixed anyway you might try media queries like so (provided you float your divs):

@media(max-width:927px){
#content{
    width: 608px;
}
#content #box2{
    float:right;
}
}

http://jsfiddle.net/5cn6ya75/8/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.