2
\$\begingroup\$

My goal was to make a list dynamically list itself into two columns, no matter the length of the list. I know this is possible by just floating the li nodes, but I wanted to keep the li nodes in the same vertical order. I would really like to hear from people who know more about JavaScript and jQuery than I do if this code looks good or if there is a better or more concise method for implementing this sort of thing.

Demo: http://jsfiddle.net/mkimitch/ZEL5x/

HTML:

<ul class="columned">
    <li>Australia</li>
    <li>Brazil</li>
    <li>Canada</li>
    <li>Chile</li>
    <li>China</li>
    <li>France</li>
    <li>India</li>
    <li>Italy</li>
    <li>Malaysia</li>
    <li>Norway</li>
    <li>Russia</li>
    <li>United Kingdom</li>
    <li>United States</li>
</ul>

JavaScript:

var colLength = $('.columned li').length;
var colHeight = $('.columned').height();
var liHeight = $('.columned li').height();
if ($('.columned li').length % 2 != 0) {
    var half = (Math.round(colHeight / 2)) + liHeight / 2;
} else {
    var half = Math.round(colHeight / 2);
}
var firstrow = Math.ceil(colLength / 2);
var secondrow = firstrow + 1;
$('.columned li:nth-child(-n+' + firstrow + ')').addClass('column1');
$('.columned li:nth-child(n+' + secondrow + ')').addClass('column2');
$('.columned li:nth-child(' + secondrow + ')').css('margin-top', -half);
\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

the best javascript is no javascript ;-)

you could use css3 columns, see http://jsfiddle.net/bjelline/JWnaz/ for the result

ul {
-moz-column-count: 2;
-moz-column-gap: 20px;
-webkit-column-count: 2;
-webkit-column-gap: 20px;
column-count: 2;
column-gap: 20px;

}

if you are worried about browser support: there's a polyfill for that http://www.csscripting.com/css-multi-column/ that falls back to javascript if the browser doesn't honor the css yet.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ that jsfiddle link goes to the original demo \$\endgroup\$
    – seand
    Commented Jan 20, 2012 at 20:13
  • \$\begingroup\$ Thanks, and yes, I am worried about browser support. I've written this code for a global Web site, so users will be using all sorts of browsers to view this, including IE6 (and maybe even IE 5.5). What's more is that the content will be translated into many different languages, and will often be updated by either someone using a WYSIWYG editor, or by someone who doesn't know a whole lot about code, so making the HTML as simple as possible is the goal. I'll definitely look into that polyfill script. Other than the implementation, how does my code look? For jQuery is it well structured? \$\endgroup\$ Commented Jan 20, 2012 at 21:39
0
\$\begingroup\$

For simpler javascript, you can just move the second half of the li elements into a new ul element, and float both of them left, so the structure looks like this:

<ul class="columned" style="float:left">
    <li>Australia</li>
    <li>Brazil</li>
    <li>Canada</li>
    <li>Chile</li>
    <li>China</li>
    <li>France</li>
    <li>India</li>
</ul>
<ul style="float:left">
    <li>Italy</li>
    <li>Malaysia</li>
    <li>Norway</li>
    <li>Russia</li>
    <li>United Kingdom</li>
    <li>United States</li>
</ul>

JavaScript:

$('.columned').each(function() {
    // divide the children
    var secondColNum = Math.ceil($(this).children('li').length / 2);

    // float first ul left
    $(this).css('float', 'left');

    // move the children to the second ul
    var secondColChildren = $(this).children('li:nth-child(n+' + secondColNum + ')');
    $('<ul style="float:left"></ul>').insertAfter($(this)).append(secondColChildren);
});

Demo: http://jsfiddle.net/PqWgj/

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.