Обертывание списков в столбцы

голоса
49

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

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

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

Задан 07/08/2008 в 17:30
источник пользователем
На других языках...                            


13 ответов

голоса
23

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

Другие решения по-прежнему приветствуются, хотя.

Ответил 07/08/2008 в 19:59
источник пользователем

голоса
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.

Ответил 08/08/2008 в 20:25
источник пользователем

голоса
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">

Ответил 07/08/2008 в 17:51
источник пользователем

голоса
5

Я сделал это с помощью 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 Lis вы можете .slice(8,14)создать новый UL вставляется после первоначальной UL, затем выберите оригинал UL и удалить Ли выбран с ul :gt(8).

Попробуйте книгу Bibeault / Katz на JQuery это большой ресурс.

Ответил 16/09/2008 в 21:37
источник пользователем

голоса
3

Вот вариация на 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!

Ответил 21/12/2009 в 19:49
источник пользователем

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

Ответил 21/09/2008 в 06:56
источник пользователем

голоса
3

Дело в том, что большинство людей забывают, что когда плавающие <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>
Ответил 16/09/2008 в 21:40
источник пользователем

голоса
3

Следующий код 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;
}
Ответил 15/09/2008 в 19:31
источник пользователем

голоса
2

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

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

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>

Ответил 30/08/2015 в 11:09
источник пользователем

голоса
2

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

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

(Но это чище JavaScript, и требует JQuery, без запасного варианта)

Далее содержит код , который изменяет массив прототип , чтобы дать новую функцию под названием «кусок» , который разрушает любой данный массив на куски заданного размера. Следующая функция называется «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);
});
Ответил 29/01/2013 в 23:26
источник пользователем

голоса
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>
Ответил 15/09/2008 в 16:45
источник пользователем

голоса
1

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

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>

Ответил 27/08/2015 в 12:29
источник пользователем

голоса
1

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

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

Пример:

смещ_по_столбцы = 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();
}
Ответил 01/07/2013 в 19:03
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more