代码之家  ›  专栏  ›  技术社区  ›  alexp206

将列表包装成列

  •  49
  • alexp206  · 技术社区  · 16 年前

    我在用 ColdFusion 填充包含以下内容的模板 HTML 列表( <ul> s)。

    其中大多数都不长,但有一些长度非常长,可以放在2-3列中。

    有没有 HTML , 冷聚变 或者也许 JavaScript (我有jquery可用)轻松做到这一点的方法吗?它不值得一些过于复杂的重量级解决方案来保存一些滚动。

    13 回复  |  直到 6 年前
        1
  •  23
  •   alexp206    16 年前

    所以我把这篇文章从另外一个列表中查出来 CSS Swag: Multi-Column Lists . 我最终使用了第一个解决方案,这不是最好的解决方案,但其他解决方案要么要求使用无法动态生成的复杂HTML,要么创建大量自定义类,这些类可以完成,但需要大量的内嵌样式,可能还需要一个巨大的页面。

    不过,其他解决方案仍然受欢迎。

        2
  •  15
  •   Nhan Jonesinator    8 年前

    如果Safari和Firefox支持对您来说足够好,那么有一个CSS解决方案:

    ul {
      -webkit-column-count: 3;
         -moz-column-count: 3;
              column-count: 3;
      -webkit-column-gap: 2em;
         -moz-column-gap: 2em;
              column-gap: 2em;
    }
    

    我对歌剧不太清楚。

        3
  •  9
  •   Peter B    6 年前

    据我所知,没有纯粹的CSS/HTML方法来实现这一点。你最好的选择是在预处理时进行。( if list length > 150, split into 3 columns, else if > 70, split into 2 columns, else 1 )

    另一个选项,使用javascript(我不熟悉 jQuery 具体来说,library)将迭代列表,可能基于列表是某个类,计算子列表的数量,如果列表的数量足够大,则在第一个列表之后动态创建一个新列表,将一些列表项转移到新列表。至于实现这些列,您可能可以将它们向左浮动,然后是具有样式的元素 clear: left clear: both .

    .column {
      float: left;
      width: 50%;
    }
    .clear {
      clear: both;
    }
    <ul class="column">
      <li>Item 1</li>
      <li>Item 2</li>
      <!-- ... -->
      <li>Item 49</li>
      <li>Item 50</li>
    </ul>
    <ul class="column">
      <li>Item 51</li>
      <li>Item 52</li>
      <!-- ... -->
      <li>Item 99</li>
      <li>Item 100</li>
    </ul>
    <div class="clear">
        4
  •  5
  •   ScottyDont    16 年前

    我已经用jquery完成了这项工作——它是跨平台的,最少有代码。

    选择ul,克隆它,并在上一个ul之后插入它。类似:

    $("ul#listname").clone().attr("id","listname2").after()
    

    这将在前一个列表之后插入一个列表副本。如果原始列表的样式是float:left,那么它们应该并排出现。

    然后可以从左侧列表中删除偶数项,从右侧列表中删除奇数项。

    $("ul#listname li:even").remove();
    $("ul#listname2 li:odd").remove();
    

    现在您有了一个从左到右的两列列表。

    若要执行更多列,请使用 .slice(begin,end) 和/或 :nth-child 选择器。 也就是说,你可以花21里士 .slice(8,14) 若要在原始保险商实验室后插入新的保险商实验室,请选择原始保险商实验室并删除所选的保险商实验室。 ul :gt(8) .

    试一下jquery上的bibeault/katz书,它是一个很好的资源。

        5
  •  4
  •   Community CDub    7 年前

    这里有一个变化 Thumbkin's 示例(使用jquery):

    var $cat_list = $('ul#catList'); // UL with all list items.
    var $cat_flow = $('div#catFlow'); // Target div.
    var $cat_list_clone = $cat_list.clone(); // Clone the list.
    $('li:odd', $cat_list).remove(); // Remove odd list items.
    $('li:even', $cat_list_clone).remove(); // Remove even list items.
    $cat_flow.append($cat_list_clone); // Append the duplicate to the target div.
    

    谢谢大拇指!

        6
  •  4
  •   Linus Caldwell Emperor 2052    11 年前

    下面的javascript代码只在spidermonkey和rhino中工作,它在e4x节点上工作——也就是说,这只对服务器端的javascript有用,但它可能会为某人提供执行jquery版本的起点。(在服务器端,它对我非常有用,但我在客户机上并不迫切需要它来实际构建它。)

    function columns(x,num) {
        num || (num = 2);
        x.normalize();
    
        var cols, i, j, col, used, left, len, islist;
        used = left = 0;
        cols = <div class={'columns cols'+num}></div>;
    
        if((left = x.length())==1)
            left = x.children().length();
        else
            islist = true;
    
        for(i=0; i<num; i++) {
            len = Math.ceil(left/(num-i));
            col = islist ? new XMLList
                         : <{x.name()}></{x.name()}>;
    
            if(!islist && x['@class'].toString())
                col['@class'] = x['@class'];
    
            for(j=used; j<len+used; j++)
                islist ? (col += x[j].copy()) 
                       : (col.appendChild(x.child(j).copy()));
    
            used += len;
            left -= len;
            cols.appendChild(<div class={'column'+(i==(num-1) ? 'collast' : '')}>{col}</div>);
        }
        return cols;
    }
    

    你称之为 columns(listNode,2) 对于两列,它会旋转:

    <ul class="foo">
      <li>a</li>
      <li>b</li>
      <li>c</li>
    </ul>
    

    进入:

    <div class="columns cols2">
      <div class="column">
        <ul class="foo">
          <li>a</li>
          <li>b</li>
        </ul>
      </div>
      <div class="column collast">
        <ul class="foo">
          <li>c</li>
        </ul>
      </div>
    </div>
    

    它应该与CSS一起使用,如下所示:

    div.columns {
        overflow: hidden;
        _zoom: 1;
    }
    
    div.columns div.column {
        float: left;
    }
    
    div.cols2 div.column {
        width: 47.2%;
        padding: 0 5% 0 0;
    }
    
    div.cols3 div.column {
        width: 29.8%;
        padding: 0 5% 0 0;
    }
    
    div.cols4 div.column {
        width: 21.1%;
        padding: 0 5% 0 0;
    }
    
    div.cols5 div.column {
        width: 15.9%;
        padding: 0 5% 0 0;
    }
    
    div.columns div.collast {
        padding: 0;
    }
    
        7
  •  4
  •   Leigh josh poley    9 年前

    大多数人忘记的是,当漂浮的时候 <li/> 项目,所有的项目必须是相同的高度,或列开始脱离正常。

    因为您使用的是服务器端语言,所以我建议使用CF将列表拆分为3个数组。然后你可以用外皮 ul 包裹3个内部 UL 像这样:

    <cfset thelist = "1,2,3,4,5,6,7,8,9,10,11,12,13">  
    <cfset container = []>  
    <cfset container[1] = []>  
    <cfset container[2] = []>  
    <cfset container[3] = []>  
    
    <cfloop list="#thelist#" index="i">  
        <cfif i mod 3 eq 0>  
            <cfset arrayappend(container[3], i)>  
        <cfelseif i mod 2 eq 0>  
            <cfset arrayappend(container[2], i)>  
        <cfelse>  
            <cfset arrayappend(container[1], i)>  
        </cfif>  
    </cfloop>  
    
    <style type="text/css"> 
        ul li { float: left; }  
        ul li ul li { clear: left; }  
    </style>  
    
    <cfoutput>  
    <ul>  
        <cfloop from="1" to="3" index="a">  
        <li>  
            <ul>  
                <cfloop array="#container[a]#" index="i">  
                <li>#i#</li>  
                </cfloop>  
            </ul>  
        </li>  
        </cfloop>  
    </ul>  
    </cfoutput>
    
        8
  •  3
  •   jonah    16 年前

    使用模块操作,可以通过插入 </ul><ul> 在你的循环中。

    <cfset numberOfColumns = 3 />
    <cfset numberOfEntries = 34 />
    <ul style="float:left;">
        <cfloop from="1" to="#numberOfEntries#" index="i">
            <li>#i#</li>
                <cfif NOT i MOD ceiling(numberOfEntries / numberOfColumns)>
                    </ul>
                    <ul style="float:left;">
                </cfif>
        </cfloop>
    </ul>
    

    使用 ceiling() 而不是 round() 以确保列表末尾没有多余的值,并且最后一列最短。

        9
  •  2
  •   Dan Roberts    16 年前

    要将列表输出到多个分组标记中,可以按这种方式循环。

    <cfset list="1,2,3,4,5,6,7,8,9,10,11,12,13,14">
    <cfset numberOfColumns = "3">
    
    <cfoutput>
    <cfloop from="1" to="#numberOfColumns#" index="col">
      <ul>
      <cfloop from="#col#" to="#listLen(list)#" index="i" step="#numberOfColumns#">
        <li>#listGetAt(list,i)#</li>
      </cfloop>
      </ul>
    </cfloop>
    </cfoutput>
    
        10
  •  2
  •   bradleygriffith    12 年前

    下面是另一个允许使用以下样式的列式列表的解决方案:

    1.      4.      7.       10.
    2.      5.      8.       11.
    3.      6.      9.       12.
    

    (但它是纯javascript,需要jquery,不需要回退)

    下面包含一些修改数组原型的代码,以提供一个名为“chunk”的新函数,该函数将任何给定数组拆分为给定大小的块。接下来是一个名为“buildcolumns”的函数,它使用一个ul选择器字符串和一个用于指定列可以包含多少行的数字。( Here is a working JSFiddle )

    $(document).ready(function(){
        Array.prototype.chunk = function(chunk_size){
            var array = this,
                new_array = [],
                chunk_size = chunk_size,
                i,
                length;
    
            for(i = 0, length = array.length; i < length; i += chunk_size){
                new_array.push(array.slice(i, i + chunk_size));
            }
            return new_array;
        }
    
        function buildColumns(list, row_limit) {
            var list_items = $(list).find('li').map(function(){return this;}).get(),
            row_limit = row_limit,
            columnized_list_items = list_items.chunk(row_limit);
    
            $(columnized_list_items).each(function(i){
                if (i != 0){
                    var item_width = $(this).outerWidth(),
                        item_height = $(this).outerHeight(),
                        top_margin = -((item_height * row_limit) + (parseInt($(this).css('margin-top')) * row_limit)),
                        left_margin = (item_width * i) + (parseInt($(this).css('margin-left')) * (i + 1));
    
                    $(this[0]).css('margin-top', top_margin);
                    $(this).css('margin-left', left_margin);
                }
            });
        }
    
        buildColumns('ul#some_list', 5);
    });
    
        11
  •  2
  •   Danield    9 年前

    FlexBox可用于在行和列方向包装项目。

    主要的想法是 flex-direction 在集装箱上 row column .

    NB:当今 browser support 相当不错。

    FIDDLE

    (标记示例取自 this old 'list apart' article )

    ol {
      display: flex;
      flex-flow: column wrap; /* flex-direction: column */
      height: 100px; /* need to specify height :-( */
    }
    ol ~ ol {
      flex-flow: row wrap; /* flex-direction: row */
      max-height: auto; /* override max-height of the column direction */
    }
    li {
      width: 150px;
    }
    a {
      display: inline-block;
      padding-right: 35px;
    }
    <p>items in column direction</p>
    <ol>
      <li><a href="#">Aloe</a>
      </li>
      <li><a href="#">Bergamot</a>
      </li>
      <li><a href="#">Calendula</a>
      </li>
      <li><a href="#">Damiana</a>
      </li>
      <li><a href="#">Elderflower</a>
      </li>
      <li><a href="#">Feverfew</a>
      </li>
      <li><a href="#">Ginger</a>
      </li>
      <li><a href="#">Hops</a>
      </li>
      <li><a href="#">Iris</a>
      </li>
      <li><a href="#">Juniper</a>
      </li>
      <li><a href="#">Kava kava</a>
      </li>
      <li><a href="#">Lavender</a>
      </li>
      <li><a href="#">Marjoram</a>
      </li>
      <li><a href="#">Nutmeg</a>
      </li>
      <li><a href="#">Oregano</a>
      </li>
      <li><a href="#">Pennyroyal</a>
      </li>
    </ol>
    <hr/>
    <p>items in row direction</p>
    <ol>
      <li><a href="#">Aloe</a>
      </li>
      <li><a href="#">Bergamot</a>
      </li>
      <li><a href="#">Calendula</a>
      </li>
      <li><a href="#">Damiana</a>
      </li>
      <li><a href="#">Elderflower</a>
      </li>
      <li><a href="#">Feverfew</a>
      </li>
      <li><a href="#">Ginger</a>
      </li>
      <li><a href="#">Hops</a>
      </li>
      <li><a href="#">Iris</a>
      </li>
      <li><a href="#">Juniper</a>
      </li>
      <li><a href="#">Kava kava</a>
      </li>
      <li><a href="#">Lavender</a>
      </li>
      <li><a href="#">Marjoram</a>
      </li>
      <li><a href="#">Nutmeg</a>
      </li>
      <li><a href="#">Oregano</a>
      </li>
      <li><a href="#">Pennyroyal</a>
      </li>
    </ol>
        12
  •  1
  •   Tim Vermaelen    11 年前

    因为我有同样的问题,找不到任何“干净”的东西,所以我想我已经发布了我的解决方案。在这个例子中,我使用了 while 循环以便使用 splice 而不是 slice . 现在的优势是splice()只需要一个索引和一个范围,其中slice()需要一个索引和总计。后者在循环时往往变得困难。

    缺点是追加时需要反转堆栈。

    例子:

    COLS=4; 李甘特=35

    对于切片为[0,9]、[9,18]、[18,27]、[27,35]的循环

    在拼接时反转=[27,8]、[18,9]、[9,9]、[0,9]

    代码:

    // @param (list): a jquery ul object
    // @param (cols): amount of requested columns
    function multiColumn (list, cols) {
        var children = list.children(),
            target = list.parent(),
            liCount = children.length,
            newUl = $("<ul />").addClass(list.prop("class")),
            newItems,
            avg = Math.floor(liCount / cols),
            rest = liCount % cols,
            take,
            stack = [];
    
        while (cols--) {
            take = rest > cols ? (avg + 1) : avg;
            liCount -= take;
    
            newItems = children.splice(liCount, take);
            stack.push(newUl.clone().append(newItems));
        }
    
        target.append(stack.reverse());
        list.remove();
    }
    
        13
  •  1
  •   Ajay Gupta    9 年前

    你可以尝试用Cols转换。

    CSS:

    ul.col {
        width:50%;
        float:left;
    }
    
    div.clr {
        clear:both;
    }
    

    HTML部分:

    <ul class="col">
        <li>Number 1</li>
        <li>Number 2</li>
    
        <li>Number 19</li>
        <li>Number 20</li>
    </ul>
    <ul class="col">
        <li>Number 21</li>
        <li>Number 22</li>
    
        <li>Number 39</li>
        <li>Number 40</li>
    </ul>