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

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

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

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

Пригоден ли вам этот плагин jquery? givainc.com/labs/mcdropdown_jquery_plugin.htm

Quog 17.09.2008 14:11

Ознакомьтесь с плагином Колонка jQuery.

phatmann 10.10.2011 19:49
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
63
2
22 213
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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">
Ответ принят как подходящий

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

Тем не менее, приветствуются и другие решения.

Печально, что два года спустя все еще нет чистого способа сделать это. Спасибо IE.

Keyo 12.07.2010 04:03

+1 Я считаю метод 6 самым чистым подходом - его можно настроить так, чтобы не использовать разметку и очень мало CSS.

entonio 21.02.2013 16:42

Если поддержка 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 я не уверен.

Я тоже использую это решение, но я теряю маркеры списка ... даже их сброс или попытка изображения не работают. Кто-нибудь?

Stefano 31.12.2012 20:08
97,8% поддержка браузера now. Check more about columns option in CSS здесь.
Nesha Zoric 22.02.2018 16:15

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

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

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

Я сделал это с помощью 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, это отличный ресурс.

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

Вот вариант примера 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!

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

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

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

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

Пример:

cols = 4; liCount = 35

цикл for с 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();
}

Вы можете попробовать это преобразовать в 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>

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>

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