views:

545

answers:

6

I have about a hundred short-text data items (this number can vary substantially) that I would like to put in a page and have the browser manage that into three columns within a surrounding div, arranged with the items going down and then across, like this:

A    F    L
B    G    M
C    H    N
D    I    O
E    K    ...

Is there a way to render this out as li's (or maybe just individual lines), and have the browser automatically collate it into three equal-height columns, possibly using CSS?

Are there any browser compatibility issues?

+1  A: 
<div style="float: left">A</div>
<div style="float: left">B</div>
<div style="float: left">C</div>
<div style="float: left">D</div>
<div style="float: left">...</div>

Then place these into a div that has its width correctly set.

griegs
What about the height of the outer div? Will that manage itself?
Robert Harvey
How does it know it's supposed to be three columns?
Robert Harvey
Yeah should do. I don't ever recall having to set the height. The issue you may have is with the content and widths.eg: if you have columns a,b,c then another row of, horndrolic,e,f then you'll have odd columns. So set the width of each of the column divs. obviously do this in a style tag. :)
griegs
It doesn't know about columns. See above comment.
griegs
OK. Thanks for the tip, but I'm going to need something that's a little more column aware.
Robert Harvey
FYI, I didn't downvote you. That was someone else.
Robert Harvey
You get that sometimes.
griegs
+1 thanks for trying.
Robert Harvey
FYI, if you have floated div's the containing div won't have any height unless you clear those div's somehow. Best way to to set "overflow: hidden;" on the containing div.
Charlino
+1  A: 

In the CSS world this is the only way I know to do three columns outside of a table of course.

<html>
    <div style="width:100px">
     <div style="float:left; width:33%;">a</div>
     <div style="float:left; width:33%;">bsdf</div>
     <div style="float:left; width:33%;">c</div>
     <div style="float:left; width:33%;">d</div>
     <div style="float:left; width:33%;">e</div>
     <div style="float:left; width:33%;">f</div>
     <div style="float:left; width:33%;">g</div>
    </div>
</html>

Clearly you wouldn't use all those style tags, instead you'd use an actual style. Notice the 33% as the width.

I tried this in IE and FirFox and no probs on either.

griegs
I also tried setting the width of the parent to 500px and the whole thing remained as three columns.
griegs
Mmm, no good. It makes three columns, but it collates left to right first. I need it to collate top to bottom first.
Robert Harvey
Isn't that just the order in which you place the inner divs? I'm pretty sure, and my css isn't expert level, that what you're asking to do is not do-able. Though now someone out there is bound to prove me wrong.
griegs
+1  A: 

html can be (actually doesnt really matters):

<div class="3col_vert">
    <div>a</div>
    <div>b</div>
    <div>c</div>
    <div>d</div>
    ...
</div>

In javascripts (example in jquery in particular), you have to wrap them with cols, so that the resulting html (after manipulation of javascript) will become:

<div class="3col_vert">
    <div class="col_left">
        <div>a</div> ...
    </div>
    <div class="col_centre">
        <div>e</div> ...
    </div>
    <div class="col_right">
        <div>g</div> ...
    </div>
</div>

Jquery to mainpulate will be:

var vert_divs = $(".3col_vert div");
// Remove them from parent
$(".3col_vert").empty()
    .append("<div class='col_left'></div>") // append the wrapper cols to parent
    .append("<div class='col_center'></div>")
    .append("<div class='col_right'></div>");

// Now place them to the wrappers
var totalDivs = vert_divs.length; // count number of match divs

vert_divs.each(function(i) {
    if (i < totalDivs / 3)
        $(this).appendTo(".3col_vert div.col_left");
    else if (i<totalDivs * 2/3)
        $(this).appendTo(".3col_vert div.col_center");
    else
        $(this).appendTo(".3col_vert div.col_right");
});

The code above isn't too optimised ( I am sure lots of better algorithm can do), but the idea is there, you use javascript to manipulate the html into something like the above one, by putting the first 1/3 to left column, second 1/3 to center, and the rest to right. The last job is use CSS to make them into 3 columns, which I am not going to cover here but there's tons of tutorials out there, for instance, this one is one of those examples.

xandy
Exactly what I was starting to write up when I saw this answer, as long as the user is familiar with jQuery it will work very well.
Odd
Before meeting jquery, I don't write client script much, javascript programming is like tackling browser difference rather than productivity. BTW, if anyone is familiar with other framework or just implement in javascript, that's still fine, as it only manipulate the markup to "help" css do its job.
xandy
Thanks, xandy. See also my new post below.
Robert Harvey
+4  A: 

Without browser compatibility issues:

<% var rows = source.Count()/3 + 1; %>
<table>
    <% for(int i=0; i<rows; i++) { %>
    <tr>
        <td><%= source.Skip(i).FirstOrDefault() %></td>
        <td><%= source.Skip(i+rows).FirstOrDefault() %></td>
        <td><%= source.Skip(i+rows*2).FirstOrDefault() %></td>
    </tr>
    <% } %>
</table>

For example look at http://stackoverflow.com/users HTML source - it uses <table>

eu-ge-ne
I think if you're not adverse to this solution it is probably the most preferable. Your resulting code will be far more efficient than having to process it client side with javascript.
Odd
This is really elegant. Candidate for the correct answer, although I did find a client-side solution, which I will post shortly.
Robert Harvey
+1  A: 

You can't do this in CSS alone - though @griegs has shown how to do across then down.

If you always want 3 columns this should be easy with a little server side code and CSS - basically for each item you write something like:

<li>item</li>

Then at count/3 and count*2/3 add:

</ul><ul>

So you end up with something like:

<style>
    .three-column-panel > ul { 
        float:left; width:33%; list-style-type: none; text-indent:0; }
</style>    

<div class="three-column-panel">
    <ul>
        <li>a</li>
        <li>b</li>
        <li>c</li>
    </ul>
    <ul>
        <li>d</li>
        <li>e</li>
        <li>f</li>
    </ul>
    <ul>
        <li>g</li>
        <li>h</li>
    </ul>
</div>
Keith
I like the idea of handling the column height server-side. It might be worth writing an HTMLHelper Extension Method.
Robert Harvey
+1  A: 

After Xandy suggested Javascript, I did some googling for jQuery plugins, and found this:

Newspaper Columns JQuery Plugin
http://www.webmeisterei.com/petznick/2007/05/16/newspaper-columns-jquery-plugin/

Usage:
You need a Container with Elements like

<div id="npContainer">
  <div class="npItem">Item1</div>
  <div class="npItem">Item2</div>
</div>

...and you need the Columns

<div id="npColumn1"></div>
<div id="npColumn2"></div>
<div id="npColumn3"></div>

In Javascript just call:

jQuery().npColumns();

A web page that uses the plugin
http://www.bregenzerwald-news.at/?classifieds=1

Robert Harvey
Interesting, robert.
xandy