我正在使用ColdFusion
填充包含HTML
列表(<ul>
)的模板。
其中大部分时间并不长,但有些人的长度非常长,而且可以真正站在2-3列。
是否有HTML
,ColdFusion
或JavaScript
(我有jQuery`可用)方式可以轻松完成此操作?保存一些滚动功能并不值得一些过于复杂的重量级解决方案。
答案 0 :(得分:24)
所以我从A List Apart CSS Swag: Multi-Column Lists挖出了这篇文章。我最终使用第一个解决方案,它不是最好的,但其他人要么使用无法动态生成的复杂HTML,要么创建大量自定义类,这可以完成,但需要大量的内嵌样式和可能是一个巨大的页面。
但仍欢迎其他解决方案。
答案 1 :(得分:15)
如果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。
答案 2 :(得分:9)
据我所知,没有纯CSS / HTML方法可以实现这一目标。您最好的选择是在预处理(if list length > 150, split into 3 columns, else if > 70, split into 2 columns, else 1
)中进行。
使用JavaScript(我不熟悉jQuery库)的另一个选择是迭代列表,可能是基于它们是某个类,计算子项数,如果是是一个足够高的数字,在第一个之后动态创建一个新列表,将一些列表项转移到新列表。就实现列而言,您可以将它们向左浮动,然后是具有样式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">
答案 3 :(得分:5)
我用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书籍,这是一个很好的资源。
答案 4 :(得分:4)
以下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;
}
答案 5 :(得分:4)
大多数人都忘记的事情是,当浮动<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>
答案 6 :(得分:4)
以下是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!
答案 7 :(得分:3)
使用模运算,您可以通过在循环期间插入</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()
,以确保列表末尾没有额外值,并且最后一列最短。
答案 8 :(得分:2)
要将列表输出到多个分组标记,您可以以这种方式循环。
<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>
答案 9 :(得分:2)
以下是另一种允许使用以下样式的圆柱列表的解决方案:
1. 4. 7. 10.
2. 5. 8. 11.
3. 6. 9. 12.
(但它是纯粹的javascript,需要jQuery,没有后备)
以下包含一些修改Array原型的代码,以提供一个名为“chunk”的新函数,该函数将任何给定的Array分解为给定大小的块。接下来是一个名为“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);
});
答案 10 :(得分:2)
Flexbox可用于在行和列方向上包装项目。
主要想法是将容器上的let task = NSURLSession.sharedSession().dataTaskWithURL(url!, ...
设置为flex-direction
或row
。
注意:现在browser support非常好。
(样本标记取自this old 'list apart' article)
column
&#13;
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;
}
&#13;
答案 11 :(得分:1)
由于我遇到了同样的问题并且找不到任何“干净”的东西,我以为我已经发布了我的解决方案。在此示例中,我使用了反向while
循环,因此我可以使用splice
代替slice
。现在的优点是splice()只需要一个索引和一个范围,其中slice()需要一个索引和总数。后者在循环时往往变得困难。
缺点是我需要在追加时反转堆栈。
示例:强>
cols = 4; liCount = 35
for slice with slice = [0,9]; [9,18]; [18,27]; [27,35]
用splice = [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();
}
答案 12 :(得分:1)
您可以尝试将其转换为cols。
CSS:
ul.col {
width:50%;
float:left;
}
div.clr {
clear:both;
}
Html Part:
<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>