Упаковка списков в столбцы

Я использую ColdFusionдля заполнения шаблона, который включает в себя неупорядоченные списки HTML <ul>.

Большинство из них не такие длинные, но некоторые имеют смехотворно большую длину и могут стоять в 2-3 столбца.

Есть ли способ сделать это с помощью HTML, ColdFusion или JavaScript (я принимаю решения jQuery)? Это не стоит слишком сложного решения, чтобы сэкономить на прокрутке.

7.08.2008 16:30:45
Вам нужен этот плагин jquery? givainc.com/labs/mcdropdown_jquery_plugin.htm
Quog 17.09.2008 10:11:45
Проверьте плагин Columnizer jQuery.
phatmann 10.10.2011 15:49:18
13 ОТВЕТОВ

Насколько я знаю, не существует чистого способа 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">

11
5.04.2018 20:06:40
РЕШЕНИЕ

Итак, я выкопал эту статью из CSS List Swag: Многостолбцовые списки . Я закончил тем, что использовал первое решение, оно не самое лучшее, но другие требуют либо использования сложного HTML, который не может быть сгенерирован динамически, либо создания большого количества пользовательских классов, которые могли бы быть выполнены, но потребовали бы множества встроенных стилей и возможно огромная страница.

Другие решения все еще приветствуются.

25
9.08.2008 06:00:06
Печально, что два года спустя все еще нет чистого способа сделать это. Спасибо IE.
Keyo 12.07.2010 00:03:41
+1 Я считаю метод 6 самым чистым подходом - его можно настроить, чтобы не использовать разметку и очень мало CSS.
entonio 21.02.2013 12:42:29

Если поддержка 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;
}

Я не уверен насчет Оперы.

16
30.11.2016 09:39:35
Я тоже на это решение, но я теряю список маркеров ... даже сброс их или попытка изображения не работает. Кто - нибудь?
Stefano 31.12.2012 16:08:34
Поддержка браузера на 97,8% . Проверьте больше о опции столбцов в CSS здесь .
Nesha Zoric 22.02.2018 13:15:26

Чтобы вывести список в несколько сгруппированных тегов, вы можете выполнить цикл таким образом.

<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>
2
15.09.2008 15:51:01

Следующий код 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;
}
4
1.06.2013 01:54:36

Я сделал это с помощью jQuery - это кроссплатформенность и минимум кода.

Выберите UL, клонируйте его и вставьте после предыдущего UL. Что-то типа:

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

Это вставит копию вашего списка после предыдущего. Если исходный список имеет стиль с плавающей точкой: слева, они должны отображаться рядом.

Затем вы можете удалить четные элементы из списка слева и нечетные элементы из списка справа.

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

Теперь у вас есть два столбца слева направо.

Чтобы сделать больше столбцов, вы хотите использовать .slice(begin,end)и / или :nth-childселектор. то есть для 21 LI вы можете .slice(8,14)создать новый UL, вставленный после вашего исходного UL, затем выбрать исходный UL и удалить выбранный li с помощью ul :gt(8).

Попробуйте книгу Bibeault / Katz на jQuery, это отличный ресурс.

5
18.09.2008 14:45:56

Большинство людей забывают о том, что при перемещении <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>
4
28.08.2015 12:42:01

Используя операцию по модулю, вы можете быстро разбить свой список на несколько списков, вставив </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()чтобы убедиться, что у вас нет дополнительных значений в конце списка и что последний столбец самый короткий.

3
21.09.2008 05:56:31

Вот вариант примера Thumbkin (с использованием 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!

4
23.05.2017 12:31:55

Вот еще одно решение, которое позволяет создавать колонные списки в следующем стиле:

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

(но это чистый javascript и требует jQuery, без отступления)

Следующее содержит некоторый код, который модифицирует прототип Array, чтобы дать новую функцию с именем 'chunk', которая разбивает любой данный массив на куски заданного размера. Далее следует функция buildColumns, которая принимает строку селектора UL и число, используемое для определения количества строк, которые могут содержать ваши столбцы. ( Вот рабочий 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);
});
2
29.01.2013 22:26:12

Поскольку у меня была та же проблема, и я не мог найти ничего «чистого», я думал, что выложил свое решение. В этом примере я использую обратный whileцикл, поэтому я могу использовать spliceвместо slice. Преимущество теперь в том, что splice () нужен только индекс и диапазон, где slice () нужен индекс и общее количество. Последний имеет тенденцию становиться трудным, зацикливаясь.

Недостатком является то, что мне нужно перевернуть стек при добавлении.

Пример:

cols = 4; liCount = 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();
}
1
1.07.2013 20:26:31

Вы можете попробовать это преобразовать в столбцы.

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>

1
27.08.2015 12:29:12

Flexbox можно использовать для упаковки элементов в направлениях строк и столбцов.

Основная идея состоит в том, чтобы установить flex-directionна контейнере либо либо, rowлибо column.

NB: В настоящее время поддержка браузеров довольно хорошая.

FIDDLE

(Образец разметки взят из этой старой статьи "list обособленно" )

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
30.08.2015 11:09:29