将列表包装成列

68

我正在使用 ColdFusion 来填充一个包含 HTML 无序列表(<ul>)的模板。

其中大多数列表长度不算很长,但有几个超级长,需要分成2-3列显示。

有没有一种简单的 HTML、ColdFusion 或者 JavaScript(我接受 jQuery 解决方案)方式来实现这个功能?为了节省滚动时间,不值得采用复杂的重量级解决方案。


这个jQuery插件对你有用吗?http://www.givainc.com/labs/mcdropdown_jquery_plugin.htm - DDM
1
请查看 Columnizer jQuery 插件。 - phatmann
13个回答

30

所以我从A List Apart中找到了这篇文章《CSS Swag: Multi-Column Lists》(多列列表)。最终我使用了第一个解决方案,虽然不是最好的选择,但其他方案要么需要使用不能动态生成的复杂HTML,要么需要创建很多自定义类,这样做需要大量的内联样式,并可能会导致页面变得非常庞大。

欢迎提供其他解决方案。


3
两年后仍然没有简单的方法做到这一点,这令人感到悲哀。感谢IE。 - Benbob
+1 我认为第六种方法最简洁 - 它可以调整为不使用标记并且只需要很少的CSS。 - entonio

18
如果你认为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;
}

我不确定Opera浏览器。


我也在使用这个解决方案,但是我的列表符号丢失了...即使重置它们或尝试使用图像也不起作用。有人知道怎么解决吗? - Stefano
现在已经有97.8%的浏览器支持CSS列选项。在这里查看更多关于CSS列选项的内容:https://kolosek.com/css-columns/。 - Nesha Zoric

14
据我所知,没有纯CSS / HTML的方法可以实现这一点。您最好的选择是在预处理中完成(如果列表长度> 150,则分成3列,否则如果> 70,则分成2列,否则为1)。
另一个选项是使用JavaScript(我不熟悉jQuery库),可能基于它们属于某个特定类别的列表进行迭代,计算子元素的数量,如果数量足够高,则动态创建一个新列表放在第一个列表之后,并将一些列表项转移到新列表中。至于实现列,则可以将它们向左浮动,然后是具有样式clear:leftclear: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">


6
我用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个LI,您可以使用.slice(8,14)创建一个新的UL插入到原始UL之后,然后选择原始UL并删除使用ul:gt(8)选择的li。
尝试使用Bibeault/Katz的jQuery书籍,这是一本很好的资源。

5

这是一个使用Jquery的Thumbkin示例变体:

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.

感谢Thumbkin!


5
以下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>

into:

<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;
}

5
大多数人忽略的问题是,当浮动
  • 项目时,所有项目必须具有相同的高度,否则列会变得混乱。
    由于您正在使用服务器端语言,我的建议是使用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>
    

  • 4
    使用取模运算,您可以在循环过程中插入</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(),确保列表末尾没有额外的值,而且最后一列是最短的。


    4

    Flexbox可以用于在行和列方向上包装项目。

    主要思想是在容器上设置flex-directionrowcolumn

    NB: 现在浏览器支持相当不错。

    FIDDLE

    (示例标记取自这篇旧的“分栏列表”文章)

    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>


    3
    为了将列表输出到多个分组标签中,您可以按照以下方式循环。
    <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>
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接