将列表包装成列

ueos 发布于 2018-03-04 cfml 最后更新 2018-03-04 01:04 688 浏览

我使用ColdFusion来填充包含HTML列表(<ul>'s)的模板。 其中大部分时间不长,但少数人的长度非常长,可以保持2-3列。 有没有HTML,ColdFusion或JavaScript(我有jQuery可用)的方式来轻松做到这一点?这不值得一些过分复杂的重量级解决方案来保存一些滚动。

已邀请:

oenim

赞同来自:

就我所知,没有纯粹的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">

ueos

赞同来自:

所以我从A List Apart CSS Swag: Multi-Column Lists中挖出了这篇文章。我最终使用了第一种解决方案,它不是最好的,但其他人需要使用无法动态生成的复杂HTML,或创建大量自定义类,这可以完成,但需要大量内联样式和可能是一个巨大的页面 其他解决方案仍然受欢迎。

dodit

赞同来自:

如果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;
}
我不确定歌剧。

enemo

赞同来自:

要将列表输出到多个分组标签,您可以按照这种方式进行循环。

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

funde

赞同来自:

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

xipsam

赞同来自:

我已经用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。 试试关于jQuery的Bibeault/Katz书籍,这是一个很好的资源。

funde

赞同来自:

大多数人忘记的是,当浮动<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>

ased

赞同来自:

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

funde

赞同来自:

这是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.
感谢Thumbkin!

kautem

赞同来自:

这是另一种解决方案,允许使用以下风格的柱状列表:

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

uet

赞同来自:

由于我有同样的问题,找不到任何“干净”的东西,我以为我发布了我的解决方案。在这个例子中,我使用了一个反向的while循环,所以我可以使用splice而不是slice。现在的优势是splice()只需要一个索引和一个范围,其中slice()需要索引和总数。后者在循环时往往变得困难。 缺点是我需要在追加时反转堆栈。 示例: cols = 4; liCount = 35 for循环与切片= [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();
}

dmodi

赞同来自:

你可以尝试这个转换成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>

dipsam

赞同来自:

Flexbox可用于在行和列方向上包装物品。 主要想法是将容器上的flex-direction设置为rowcolumn。 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>