简体   繁体   中英

css column layout issue

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/

在此处输入图片说明

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.

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 div s expand to fill all available space, and how the columns are spaced.

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).

 $( 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

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.

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/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM