Envolvendo listas em colunas

votos
49

Eu estou usando ColdFusionpara preencher um modelo que inclui HTMLlistas ( <ul>'s).

A maioria destes não são tão longa, mas alguns têm comprimentos ridiculamente longas e realmente poderia estar para estar em 2-3 colunas.

Existe um HTML, ColdFusionou talvez JavaScript(eu tenho jQuery` disponível) maneira de fazer isso facilmente? Não vale a pena alguma solução forte peso sobre-complicada para poupar algum rolagem.

Publicado 07/08/2008 em 17:30
fonte usuário
Em outras línguas...                            


13 respostas

votos
23

Então eu desenterrar este artigo de A List Apart Ganhos CSS: Listas de várias colunas . Acabei usando a primeira solução, não é o melhor, mas os outros exigem ou usando HTML complexa que não pode ser gerado dinamicamente, ou a criação de um monte de classes personalizadas, o que poderia ser feito, mas exigiria um monte de styling em linha e possivelmente uma página enorme.

Outras soluções ainda bem-vindo embora.

Respondeu 07/08/2008 em 19:59
fonte usuário

votos
15

Se o suporte Safari e Firefox é bom o suficiente para você, há uma solução CSS:

ul {
  -webkit-column-count: 3;
     -moz-column-count: 3;
          column-count: 3;
  -webkit-column-gap: 2em;
     -moz-column-gap: 2em;
          column-gap: 2em;
}

Eu não tenho certeza sobre Opera.

Respondeu 08/08/2008 em 20:25
fonte usuário

votos
9

Não há nenhuma maneira pura CSS / HTML para conseguir isso, tanto quanto eu sei. Sua melhor aposta seria a fazê-lo em pré-processamento ( if list length > 150, split into 3 columns, else if > 70, split into 2 columns, else 1).

A outra opção, usando JavaScript (Eu não estou familiarizado com o jQuery biblioteca especificamente) seria para percorrer listas, provavelmente com base nelas sendo uma certa classe, contar o número de filhos, e se é um número suficientemente elevado, de forma dinâmica criar uma nova lista depois do primeiro, transferindo algum número de itens da lista para a nova lista. Tanto quanto a implementação das colunas, você provavelmente poderia flutuar-los esquerda, seguido por um elemento que tinha o estilo clear: leftou 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">

Respondeu 07/08/2008 em 17:51
fonte usuário

votos
5

Eu fiz isso com jQuery - é multi-plataforma e um mínimo de código.

Selecione a UL, cloná-lo e inseri-lo após a UL anterior. Algo como:

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

Isto irá inserir uma cópia de sua lista após a anterior. Se a lista original é denominado com um float: left, eles devem aparecer lado a lado.

Em seguida, você pode excluir os mesmo itens da lista do lado esquerdo e os itens ímpares a partir da lista direita.

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

Agora você tem uma esquerda para a lista direita duas colunas.

Para fazer mais colunas que você vai querer usar .slice(begin,end)e / ou o :nth-childselector. ou seja, para 21 LIs você poderia .slice(8,14)criar uma nova UL inserido após o seu UL original, em seguida, selecione a UL original e excluir o li do selecionado com ul :gt(8).

Tente o livro Bibeault / Katz em jQuery é um grande recurso.

Respondeu 16/09/2008 em 21:37
fonte usuário

votos
3

Aqui é uma variação do Thumbkin exemplo (usando 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.

Graças Thumbkin!

Respondeu 21/12/2009 em 19:49
fonte usuário

votos
3

Usando uma operação de módulo, você pode rapidamente dividir sua lista em várias listas através da inserção de um </ul><ul>durante o seu ciclo.

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

Use ceiling()em vez de round()para garantir que você não tem valores extras no final da lista e que a última coluna é mais curto.

Respondeu 21/09/2008 em 06:56
fonte usuário

votos
3

A única coisa que a maioria das pessoas estão esquecendo é que, quando flutuando <li/>itens, todos os itens tem que ser a mesma altura, ou as colunas começar a ficar fora de sintonia.

Desde que você está usando uma linguagem do lado do servidor, a minha recomendação seria usar CF para dividir a lista em 3 matrizes. Em seguida, você pode usar um externo ulpara embrulhar o interior 3 ulda seguinte forma:

<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>
Respondeu 16/09/2008 em 21:40
fonte usuário

votos
3

O seguinte código JavaScript funciona apenas em Macaco-Aranha e Rhino, e opera em nós E4X - ou seja, isso é útil apenas para server-side JavaScript, mas pode dar a alguém um ponto de partida para fazer uma versão jQuery. (Tem sido muito útil para mim no lado do servidor, mas eu não precisava dele no cliente mal o suficiente para realmente construí-lo.)

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

Você chamá-lo assim columns(listNode,2)para duas colunas, e verifica-se:

<ul class="foo">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>

para dentro:

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

É concebido para ser usado com CSS como este:

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;
}
Respondeu 15/09/2008 em 19:31
fonte usuário

votos
2

Flexbox pode ser usado para embrulhar itens em ambas as linhas e colunas direções.

A idéia principal é definir a flex-directionno recipiente, quer rowou column.

NB: Hoje em dia o suporte ao navegador é muito bom.

FIDDLE

(Markup amostra retirada de este velho 'List Apart' artigo )

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>

Respondeu 30/08/2015 em 11:09
fonte usuário

votos
2

Aqui é outra solução que permite listas com colunas no estilo seguinte:

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

(Mas é puro javascript, e exige jQuery, sem fallback)

A seguir contém um algum código que modifica o protótipo Array para dar uma nova função chamada 'pedaço' que quebra qualquer matriz dada em pedaços de um determinado tamanho. Em seguida é uma função chamada 'buildColumns' que leva uma string selector UL e um número usado para designar quantas linhas suas colunas podem conter. ( Aqui está uma jsFiddle trabalhando )

$(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);
});
Respondeu 29/01/2013 em 23:26
fonte usuário

votos
2

Para emitir a lista em tag múltiplos agrupados você pode fazer um loop desta forma.

<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>
Respondeu 15/09/2008 em 16:45
fonte usuário

votos
1

Você pode tentar este para converter em cols.

CSS:

ul.col {
    width:50%;
    float:left;
}

div.clr {
    clear:both;
}

Html Parte:

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

Respondeu 27/08/2015 em 12:29
fonte usuário

votos
1

Desde que eu tive o mesmo problema e não consegui encontrar nada "limpar" Eu pensei que eu tinha postado minha solução. Neste exemplo, eu uso uma invertida whilecircuito que eu possa usar spliceem vez de slice. A vantagem é agora splicing () necessita apenas de um índice e um intervalo em fatia () necessita de um índice de eo total. A última tende a tornar-se difícil ao loop.

Desvantagem é que eu preciso para reverter a pilha enquanto anexando.

Exemplo:

cols = 4; liCount = 35

loop com fatia = [0, 9]; [9, 18]; [18, 27]; [27, 35]

invertido, enquanto com splicing = [27, 8]; [18, 9]; [9, 9]; [0, 9]

Código:

// @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();
}
Respondeu 01/07/2013 em 19:03
fonte usuário

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