Domanda

sto usando ColdFusion per popolare un modello che include HTML elenchi (<ul>'S).

La maggior parte di questi non sono così lunghi, ma alcuni hanno lunghezze ridicolmente lunghe e potrebbero davvero stare in 2-3 colonne.

C'è un HTML, ColdFusion o forse JavaScript (Ho jQuery` disponibile) modo per farlo facilmente?Non vale la pena utilizzare una soluzione pesante e troppo complicata per risparmiare un po' di scorrimento.

È stato utile?

Soluzione

Così ho tirato fuori questo articolo da A List Apart Premio CSS:Elenchi a più colonne.Alla fine ho utilizzato la prima soluzione, non è la migliore ma le altre richiedono l'utilizzo di HTML complesso che non può essere generato dinamicamente o la creazione di molte classi personalizzate, cosa che potrebbe essere eseguita ma richiederebbe un sacco di stili in linea e forse una pagina enorme.

Altre soluzioni sono comunque benvenute.

Altri suggerimenti

Se il supporto di Safari e Firefox è abbastanza buono per te, esiste una soluzione CSS:

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

Non sono sicuro dell'Opera.

Per quanto ne so, non esiste un metodo CSS/HTML puro per raggiungere questo obiettivo.La soluzione migliore sarebbe farlo in pre-elaborazione (if list length > 150, split into 3 columns, else if > 70, split into 2 columns, else 1).

L'altra opzione, utilizzando JavaScript (non ho familiarità con il file jQuery libreria in particolare) sarebbe quello di scorrere gli elenchi, probabilmente in base al fatto che sono una determinata classe, contare il numero di figli e, se è un numero sufficientemente alto, creare dinamicamente un nuovo elenco dopo il primo, trasferendo un certo numero di elementi dell'elenco a il nuovo elenco.Per quanto riguarda l'implementazione delle colonne, potresti probabilmente farle galleggiare a sinistra, seguite da un elemento che abbia lo stile 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">

L'ho fatto con jQuery: è multipiattaforma e richiede un minimo di codice.

Seleziona l'UL, clonalo e inseriscilo dopo l'UL precedente.Qualcosa di simile a:

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

Questo inserirà una copia del tuo elenco dopo quello precedente.Se l'elenco originale ha uno stile float:left, dovrebbero apparire fianco a fianco.

Quindi puoi eliminare gli elementi pari dall'elenco di sinistra e gli elementi dispari dall'elenco di destra.

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

Ora hai un elenco di due colonne da sinistra a destra.

Per fare più colonne che vorrai utilizzare .slice(begin,end) e/o il :nth-child selettore.cioè, per 21 LI potresti .slice(8,14) per creare un nuovo UL inserito dopo il tuo UL originale, quindi seleziona l'UL originale ed elimina gli li selezionati con ul :gt(8).

Prova il libro Bibeault/Katz su jQuery è un'ottima risorsa.

Ecco una variazione su Di Thumbkin esempio (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.

Grazie Thumbkin!

Il seguente codice JavaScript funziona solo in Spidermonkey e Rhino e funziona sui nodi E4X, ovvero è utile solo per JavaScript lato server, ma potrebbe fornire a qualcuno un punto di partenza per realizzare una versione jQuery.(Mi è stato molto utile sul lato server, ma non ne ho avuto abbastanza bisogno sul client per costruirlo effettivamente.)

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 chiami così columns(listNode,2) per due colonne, e risulta:

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

in:

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

È pensato per essere utilizzato con i CSS in questo modo:

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

La cosa che la maggior parte delle persone dimentica è che quando galleggia <li/> elementi, tutti gli elementi devono avere la stessa altezza, altrimenti le colonne iniziano a perdere colpi.

Poiché stai utilizzando un linguaggio lato server, il mio consiglio sarebbe di utilizzare CF per dividere l'elenco in 3 array.Quindi puoi usare un esterno ul per avvolgere i 3 interni ul così:

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

Utilizzando un'operazione modulo, puoi dividere rapidamente l'elenco in più elenchi inserendo a </ul><ul> durante il tuo 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>

Utilizzo ceiling() invece di round() per assicurarti di non avere valori aggiuntivi alla fine dell'elenco e che l'ultima colonna sia la più breve.

Per generare l'elenco in più tag raggruppati è possibile eseguire il loop in questo modo.

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

Ecco un'altra soluzione che consente elenchi in colonne nel seguente stile:

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

(ma è puro Javascript e richiede jQuery, senza fallback)

Quanto segue contiene un codice che modifica il prototipo dell'Array per fornire una nuova funzione chiamata 'chunk' che suddivide un dato Array in blocchi di una determinata dimensione.La prossima è una funzione chiamata "buildColumns" che accetta una stringa di selezione UL e un numero utilizzato per designare quante righe possono contenere le colonne.(Ecco un JSFiddle funzionante)

$(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 può essere utilizzato per avvolgere gli elementi sia in direzione di riga che di colonna.

L'idea principale è impostare il file flex-direction sul contenitore a entrambi row O column.

NB:Al giorno d'oggi supporto del browser è abbastanza buono

VIOLINO

(Markup di esempio tratto da questo vecchio articolo "lista a parte".)

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>

Dato che ho avuto lo stesso problema e non sono riuscito a trovare nulla di "pulito", ho pensato di pubblicare la mia soluzione.In questo esempio utilizzo un reverse while loop così posso usarlo splice invece di slice.Il vantaggio ora è che splice() necessita solo di un indice e un intervallo mentre slice() necessita di un indice e del totale.Quest'ultimo tende a diventare difficile durante il looping.

Lo svantaggio è che devo invertire lo stack durante l'aggiunta.

Esempio:

colonne = 4;liConte = 35

ciclo for con porzione = [0, 9];[9, 18];[18, 27];[27, 35]

invertito mentre con giunzione = [27, 8];[18, 9];[9, 9];[0, 9]

Codice:

// @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();
}

Puoi provare questo per convertire in 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>

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top