Вопрос

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

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

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

Это было полезно?

Решение

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

Однако другие решения по-прежнему приветствуются.

Другие советы

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

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

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

Я сделал это с помощью 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 и удалите выбранные li с помощью ul :gt(8).

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

Вот вариация на тему 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.

Спасибо, Тамбкин!

Следующий код 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;
}

Большинство людей забывают, что при плавании <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>

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

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

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

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

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

(но это чистый JavaScript и требует jQuery без резервного варианта)

Ниже приведен код, который изменяет прототип массива, чтобы создать новую функцию под названием «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);
});

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

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

Примечание:Настоящее время поддержка браузера это довольно хорошо.

СКРИПКА

(Пример разметки взят из эта старая статья, посвященная раздельному списку)

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>

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

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

Пример:

столбцы = 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();
}

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

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>

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top