0

I'm writing a web page that needs to display content in boxes, like this:

[ 1 ] [ 3 ] [ 5 ]
[ 2 ] [ 4 ] [ 6 ]

Because of varying screen sizes, sometimes the number of rows will vary. For example, a screen that allows for more row to be shown would be arranged like this:

[ 1 ] [ 4 ]
[ 2 ] [ 5 ]
[ 3 ] [ 6 ]

The problem I'm running in to is that when I just float the DIVs to the left, they show up like this:

[ 1 ] [ 2 ] [ 3 ]
[ 4 ] [ 5 ] [ 6 ]

My plan to fix this is to wrap each column in a div, and float that to the left. But because there can be a varying number of rows depending on screen size, I need to accomplish this with jQuery.

I've already counted the number of rows with jQuery, I just can't figure out how to wrap a certain number of divs in a wrapper. Here's my script so far:

var pageHeight = $("body").innerHeight() - 157; // 157 being the height of the page title
var rowCount = Math.floor(pageHeight / 295); // 295 being the height of each item
var itemCount = $("#itemWrapper").children(".item").length;each item
$("#itemWrapper").height(pageHeight);

So, if rowCount = 3, then I need to wrap the each set of three .items in <div class="column"></div>. And of course remember that there may be only two, or one .item left over.

This seems pretty simple, but I'm having trouble even finding where to begin. As I research this some more, if I figure anything out, I'll be sure to update my question.

UPDATE 1: Looks like I may be able to use the .wrap() function of jQuery. I just need to figure out how to use it on more than one DIV.

UPDATE 2: I found this bit of code, that looks promising, but I can't figure out how to make it change based on the number of rows:

for (var i = 0;i < itemCount;i+=3) {
    $(".item").filter(':eq('+i+'),:eq('+(i+1)+'),:eq('+(i+2)+')').wrapAll('<div class="column" />');
};

It seems like for each additional div, it needs to add anther :eq('+(i+1)+') with one number higher. Not sure how to write script that does that, but I'm still researching. If I just change the 3' torowCount` it doesn't properly close all the added divs.

JacobTheDev
  • 17,318
  • 25
  • 95
  • 158
  • 1
    If you don't mind cross-browser issues, use a vertical flexbox: http://jsfiddle.net/HJr3H/. – pimvdb Jan 01 '13 at 21:47
  • Needs to work in IE10 (it's going to be for a Windows 8 HTML5 app), plus that doesn't appear to be working correctly in Chrome (it all appears in one column). – JacobTheDev Jan 01 '13 at 21:50
  • Y'know, if you thik about it, there's no "real" construct that equals the behavior of a self-stacking column. – Jared Farrish Jan 01 '13 at 21:52

3 Answers3

3

You can use CSS3 column properties for browsers that support them.

Here's a column wrapping script that will work cross browser. I used a css rule for column class based on column count to set width in percentage

var colCount = 3,/* hard coded for demo, use your calcs for dynamic*/
    $items = $('.item'),
    items_per_col = Math.ceil($items.length / colCount),
    start = 0;

for (i = 0; i < colCount; i++) {
    var endSlice = start + items_per_col;
    $items.slice(start, endSlice).wrapAll('<div class="col' + colCount + '">');
    start += items_per_col;
}

DEMO: http://jsfiddle.net/MkGyu/1

charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Perfect! I had to tweak it a bit to fit with my current code, but this works exactly how I imagined. Thanks! – JacobTheDev Jan 01 '13 at 22:03
  • Gee, I [had a CSS anwwer refrence](http://stackoverflow.com/questions/7617418/how-is-a-css-display-table-column-supposed-to-work) but put my money on Masonry. Oh well. – Jared Farrish Jan 01 '13 at 22:08
  • @JaredFarrish Masonry's pretty cool, but likely overkill for these few lines that can also be quickly adapted to a resize handler – charlietfl Jan 01 '13 at 22:11
  • Everyone knows style over substance, except when it's me betting on red. `:O` – Jared Farrish Jan 01 '13 at 22:19
2

I can't comment yet, so sorry for posting this as an answer.

You should really look into responsive web design using media queries. Here's an article to get you started.

Community
  • 1
  • 1
0
if (jQuery and wantsColumns) {
   return [Masonry](http://masonry.desandro.com/demos/basic-multi-column.html);
}
Jared Farrish
  • 48,585
  • 17
  • 95
  • 104
  • This looks interesting, but it looks like I'd still need to count the number of divs with jQuery to properly resize, so it doesn't answer the question. – JacobTheDev Jan 01 '13 at 21:58
  • You'd still have to count the what? Take a look around, there's all kinds of crazy stuff it does. – Jared Farrish Jan 01 '13 at 22:01