开发者

Javascript to turn an unordered list into multiple columns

开发者 https://www.devze.com 2023-01-06 15:06 出处:网络
There doesn\'t seem to be an 开发者_StackOverfloweasy way in (well supported) css to do this. I\'m looking for a javascript solution, preferably jQuery.

There doesn't seem to be an 开发者_StackOverfloweasy way in (well supported) css to do this. I'm looking for a javascript solution, preferably jQuery.

I have an unordered list like this:

<ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
    <li>E</li>        
    ...etc
</ul>

I want each column to have a height for example four items and fill vertically rather than horizontally like a css float:

A     E
B     F
C
D


You will want to use a combination of CSS and jQuery, but in theory it is very simple. Render a complete single list in HTML, then provide a wrapper via jQuery and split the list up as desired. The following function does just that. Be sure to use a more specific selector than just ul when actually using the script. An id would be ideal.

View demo here.

jQuery(function ($) {
  var size = 4,
      $ul  = $("ul"),
      $lis = $ul.children().filter(':gt(' + (size - 1) + ')'),
      loop = Math.ceil($lis.length / size),
      i    = 0;

  $ul.css('float', 'left').wrap("<div style='overflow: hidden'></div>");

  for (; i < loop; i = i + 1) {
    $ul = $("<ul />").css('float', 'left').append($lis.slice(i * size, (i * size) + size)).insertAfter($ul);
  }
});


See this article:

One of the minor holy grails of XHTML and CSS is to produce a single, semantically logical ordered list that wraps into vertical columns.

I’ll warn you up front. If you want to present a list in multiple columns, you’ll have to compromise. You can sacrifice W3C web standards and use deprecated markup, you can live with markup that’s less than semantically logical, you can tolerate a mixture of presentation with content, you can say goodbye to browser compatibility, or you can use markup that’s heavy with attributes and styling that’s heavy with rules. Every road exacts a toll.

http://www.alistapart.com/articles/multicolumnlists/

The "best" solution is subjective, but I'd be inclined towards arbitrary classes.


Doug's solution is nice if you want to split the list up into sub lists.

Instead I chose to position the list elements without changing the dom. This is a bit messy, basically it puts a left margin on each element which is the column number multiplied by the column width. This will result in a staircase layout so the next step was to add some negative top margin to bring each element up to the top.

Basically this displays as a grid. I am using this for drop down menus so it worked well. Avoid using this if you need each list item to have a dynamic height. The col_height variable could be set to the height of the largest item to make the code a bit more general purpose.

var col_max_height = 6; //Max Items per column
var col_width = 200; //Pixels
var col_height = 33; //Pixels
$('.header ul li ul').each(function() {
    $(this).find('li').each(function(index){
        column = parseInt(index/col_max_height);
        $(this).css('margin-left', column * col_width + 'px')
        if(column > 0) {
            $(this).css('margin-top', (index - (col_max_height * column)  + 1) * -col_height + 'px').addClass('col_'+column);
        }
    });
});


@Keyo, thanks for your helpful answer.

Just a few modification needed to make it work on my end.
(Formula was changed, perhaps it could help someone)

var col_max_item = 2; //Max Items per column
var col_width = $('.header ul li').css('width').replace("px", "");  //Pixels, get width from CSS
var col_height = $('.header ul li').css('height').replace("px", ""); //Pixels, get height from CSS  

    $('.header ul').each(function() { 
        $(this).find('li').each(function(index){ 
            column = parseInt(index/col_max_item);
            $(this).css('margin-left', column * col_width + 'px')
            if(column > 0 && (index / col_max_item) == column) {
                $(this).css('margin-top', (col_max_item * col_height * -1)  + 'px').addClass('col_'+column);
            }
        });
    });


for this I use a plugin called "Easy List Splitter". here is the link:

http://www.madeincima.it/en/articles/resources-and-tools/easy-list-splitter-plugin/


Just a little different moves up the next column instead of each li.

var col_max_height = 6; //Max Items per column
var col_width = 120; //Pixels
var prevCol = 0; 
$('.header ul').each(function() {
    $(this).find('li').each(function(index){
    column = parseInt(index/col_max_height);
    $(this).css('margin-left', column * col_width + 'px')
        if(prevCol != column) {
            $(this).css('margin-top',  '-92px').addClass('col_'+column);
            prevCol = column;
        } else {
            $(this).css('margin-top',  '0px').addClass('col_'+column);
        }
    });
});


You can do this really easily with the jQuery-Columns Plugin for example to split a ul with a class of .mylist you would do

$('.mylist').cols(2);

Here's a live example on jsfiddle

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号