Envolver listas en columnas


Estoy usando ColdFusion para rellenar una plantilla que incluye HTML listas (<ul>'s).

La mayoría de estos no son tan largos, pero algunos tienen longitudes ridículamente largas y realmente podrían estar en 2-3 columnas.

Hay un HTML, ColdFusion o tal vez JavaScript (tengo jQuery` disponible) manera de hacer esto fácilmente? No vale la pena alguna solución de peso pesado demasiado complicada para ahorrar algo de desplazamiento.

Author: Alive to Die, 2008-08-07

13 answers

Así que desenterré este artículo de Una Lista Aparte Swag CSS: Listas de varias columnas. Terminé usando la primera solución, no es la mejor, pero las otras requieren usar HTML complejo que no se puede generar dinámicamente, o crear muchas clases personalizadas, lo que podría hacerse, pero requeriría un montón de estilo en línea y posiblemente una página enorme.

Otras soluciones son bienvenidas.

 23
Author: alexp206,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-09 06:00:06

Si el soporte de Safari y Firefox es lo suficientemente bueno para usted, hay una solución CSS:

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

No estoy seguro de la Ópera.

 15
Author: doekman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-30 09:39:35

No hay una forma pura de CSS/HTML para lograr esto, por lo que sé. Su mejor opción sería hacerlo en pre-procesamiento (if list length > 150, split into 3 columns, else if > 70, split into 2 columns, else 1).

La otra opción, usando JavaScript (no estoy familiarizado con la biblioteca jQuery específicamente) sería iterar a través de listas, probablemente basadas en que son una clase determinada, contar el número de hijos, y si es un número lo suficientemente alto, crear dinámicamente una nueva lista después de la primera, transfiriendo algún número de elementos de la lista a la nueva lista. En cuanto a implementar las columnas, probablemente podría flotarlas a la izquierda, seguido de un elemento que tuviera el estilo clear: left o 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">
 9
Author: Chris Marasti-Georg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-05 20:06:40

He hecho esto con jQuery - es multiplataforma y un mínimo de código.

Seleccione la UL, clónela e insértela después de la UL anterior. Algo como:

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

Esto insertará una copia de su lista después de la anterior. Si la lista original tiene un estilo float: left, deben aparecer una al lado de la otra.

Luego puede eliminar los elementos pares de la lista de la izquierda y los elementos impares de la lista de la derecha.

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

Ahora tienes dos de izquierda a derecha lista de columnas.

Para hacer más columnas querrás usar .slice(begin,end) y/o el selector :nth-child. es decir, para 21 LIs podría .slice(8,14) para crear una nueva UL insertada después de su UL original, luego seleccione la UL original y elimine las li seleccionadas con ul :gt(8).

Pruebe el libro Bibeault/Katz en jQuery es un gran recurso.

 5
Author: ScottyDont,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 14:45:56

Aquí hay una variación del ejemplo de Thumbkin (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.

Gracias Thumbkin!

 4
Author: Community,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:31:55

El siguiente código JavaScript solo funciona en Spidermonkey y Rhino, y opera en nodos E4X i es decir, esto es útil solo para JavaScript del lado del servidor, pero podría darle a alguien un punto de partida para hacer una versión de jQuery. (Ha sido muy útil para mí en el lado del servidor,pero no lo he necesitado en el cliente lo suficiente como para construirlo.)

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

Lo llamas como columns(listNode,2) para dos columnas, y gira:

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

En:

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

Está destinado a ser utilizado con CSS así:

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
Author: Linus Caldwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-01 01:54:36

Lo que la mayoría de la gente está olvidando es que cuando flotan elementos <li/>, todos los elementos tienen que tener la misma altura, o las columnas comienzan a salirse de control.

Dado que está utilizando un lenguaje del lado del servidor, mi recomendación sería usar CF para dividir la lista en 3 matrices. Entonces puedes usar un ul externo para envolver los 3 ul internos de la siguiente manera:

<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
Author: Leigh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-28 12:42:01

Usando una operación de módulo, puede dividir rápidamente su lista en varias listas insertando un </ul><ul> durante su bucle.

<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() en lugar de round() para asegurarse de que no tiene valores adicionales al final de la lista y que la última columna es más corta.

 3
Author: jonah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-21 05:56:31

Para generar la lista en múltiples etiquetas agrupadas, puede realizar un bucle de esta manera.

<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
Author: Dan Roberts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-15 15:51:01

Aquí hay otra solución que permite listas con columnas en el siguiente estilo:

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

(pero es javascript puro, y requiere jQuery, sin respaldo)

Lo siguiente contiene un código que modifica el prototipo de matriz para dar una nueva función llamada 'chunk' que rompe cualquier matriz dada en trozos de un tamaño dado. A continuación hay una función llamada 'buildColumns' que toma una cadena de selector UL y un número utilizado para designar cuántas filas pueden contener sus columnas. (Aquí hay un JSFiddle que funciona )

$(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
Author: bradleygriffith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-29 22:26:12

Flexbox se puede usar para envolver elementos en direcciones de fila y columna.

La idea principal es establecer el flex-direction en el contenedor en row o column.

NB: Hoy en día el soporte del navegador es bastante bueno.

FIDDLE

(Marcado de muestra tomado de este antiguo artículo 'list apart' )

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>
 2
Author: Danield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-30 11:09:29

Ya que tenía el mismo problema y no podía encontrar nada "limpio" pensé que había publicado mi solución. En este ejemplo utilizo un bucle invertido while para poder usar splice en lugar de slice. La ventaja ahora es que splice() solo necesita un índice y un rango donde slice () necesita un índice y el total. Este último tiende a ser difícil durante el bucle.

La desventaja es que necesito invertir la pila mientras añado.

Ejemplo:

Cols = 4; liCount = 35

Para bucle con slice = [0, 9]; [9, 18]; [18, 27]; [27, 35]

Invertido, mientras que con empalme = [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();
}
 1
Author: Tim Vermaelen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-01 20:26:31

Puede probar esto para convertir en cols.

CSS:

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

div.clr {
    clear:both;
}

Parte 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
Author: Ajay Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-27 12:29:12