Question

j'utilise ColdFusion pour remplir un modèle qui inclut HTML listes (<ul>'s).

La plupart d'entre eux ne sont pas si longs, mais quelques-uns ont des longueurs ridiculement longues et pourraient vraiment figurer sur 2-3 colonnes.

Y'a-t-il un HTML, ColdFusion ou peut-être JavaScript (J'ai jQuery disponible) un moyen de le faire facilement ?Cela ne vaut pas la peine d'utiliser une solution lourde et trop compliquée pour économiser du défilement.

Était-ce utile?

La solution

J'ai donc déterré cet article de A List Apart Objet CSS :Listes multicolonnes.J'ai fini par utiliser la première solution, ce n'est pas la meilleure mais les autres nécessitent soit d'utiliser du HTML complexe qui ne peut pas être généré dynamiquement, soit de créer de nombreuses classes personnalisées, ce qui pourrait être fait mais nécessiterait beaucoup de style en ligne et peut-être une énorme page.

D’autres solutions restent cependant les bienvenues.

Autres conseils

Si la prise en charge de Safari et Firefox vous suffit, il existe une solution CSS :

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

Je ne suis pas sûr pour Opera.

Pour autant que je sache, il n'existe pas de moyen pur CSS/HTML d'y parvenir.Votre meilleur pari serait de le faire en pré-traitement (if list length > 150, split into 3 columns, else if > 70, split into 2 columns, else 1).

L'autre option, en utilisant JavaScript (je ne connais pas le jQuery bibliothèque en particulier) serait de parcourir les listes, probablement en fonction du fait qu'elles appartiennent à une certaine classe, de compter le nombre d'enfants et, si le nombre est suffisamment élevé, de créer dynamiquement une nouvelle liste après la première, en transférant un certain nombre d'éléments de liste vers la nouvelle liste.En ce qui concerne l'implémentation des colonnes, vous pourriez probablement les faire flotter vers la gauche, suivies d'un élément ayant le style clear: left ou 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">

Je l'ai fait avec jQuery - c'est multiplateforme et un minimum de code.

Sélectionnez l'UL, clonez-la et insérez-la après l'UL précédente.Quelque chose comme:

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

Cela insérera une copie de votre liste après la précédente.Si la liste d'origine est stylisée avec float:left, elles doivent apparaître côte à côte.

Ensuite, vous pouvez supprimer les éléments pairs de la liste de gauche et les éléments impairs de la liste de droite.

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

Vous avez maintenant une liste de deux colonnes de gauche à droite.

Pour créer plus de colonnes, vous souhaiterez utiliser .slice(begin,end) et/ou le :nth-child sélecteur.c'est-à-dire que pour 21 LI, vous pourriez .slice(8,14) pour créer une nouvelle UL insérée après votre UL d'origine, puis sélectionnez l'UL d'origine et supprimez les li sélectionnés avec ul :gt(8).

Essayez le livre Bibeault/Katz sur jQuery, c'est une excellente ressource.

Voici une variante de Pouce exemple (en utilisant 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.

Merci Poucette !

Le code JavaScript suivant ne fonctionne que dans Spidermonkey et Rhino, et il fonctionne sur les nœuds E4X - c'est-à-dire qu'il n'est utile que pour le JavaScript côté serveur, mais il pourrait donner à quelqu'un un point de départ pour créer une version jQuery.(Cela m'a été très utile côté serveur, mais je n'en ai pas assez eu besoin sur le client pour le construire.)

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

Tu appelles ça comme columns(listNode,2) pour deux colonnes, et ça donne :

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

dans:

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

Il est destiné à être utilisé avec CSS comme ceci :

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

Ce que la plupart des gens oublient, c'est que lorsqu'ils flottent <li/> éléments, tous les éléments doivent avoir la même hauteur, sinon les colonnes commencent à se dérégler.

Puisque vous utilisez un langage côté serveur, ma recommandation serait d'utiliser CF pour diviser la liste en 3 tableaux.Ensuite, vous pouvez utiliser un extérieur ul pour envelopper les 3 intérieurs ul ainsi:

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

À l'aide d'une opération modulo, vous pouvez rapidement diviser votre liste en plusieurs listes en insérant un </ul><ul> pendant votre boucle.

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

Utiliser ceiling() au lieu de round() pour vous assurer que vous n'avez pas de valeurs supplémentaires à la fin de la liste et que la dernière colonne est la plus courte.

Pour afficher la liste dans plusieurs balises groupées, vous pouvez effectuer une boucle de cette façon.

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

Voici une autre solution qui permet d'avoir des listes en colonnes dans le style suivant :

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

(mais c'est du javascript pur et nécessite jQuery, sans solution de secours)

Ce qui suit contient du code qui modifie le prototype Array pour donner une nouvelle fonction appelée « morceau » qui divise n'importe quel tableau donné en morceaux d'une taille donnée.Vient ensuite une fonction appelée « buildColumns » qui prend une chaîne de sélection UL et un nombre utilisé pour désigner le nombre de lignes que vos colonnes peuvent contenir.(Voici un JSFiddle fonctionnel)

$(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 peut être utilisé pour envelopper des éléments dans le sens des lignes et des colonnes.

L'idée principale est de définir le flex-direction sur le conteneur soit row ou column.

Attention :Aujourd'hui prise en charge du navigateur c'est plutôt bien.

VIOLON

(Exemple de balisage tiré de ce vieil article sur la « liste à part »)

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>

Comme j'ai eu le même problème et que je n'ai rien trouvé de "propre", j'ai pensé avoir publié ma solution.Dans cet exemple, j'utilise un inversé while boucle pour que je puisse l'utiliser splice au lieu de slice.L'avantage est maintenant que splice() n'a besoin que d'un index et d'une plage où slice() a besoin d'un index et du total.Ce dernier a tendance à devenir difficile en boucle.

L'inconvénient est que je dois inverser la pile lors de l'ajout.

Exemple:

colonnes = 4 ;liCount = 35

boucle for avec tranche = [0, 9] ;[9, 18];[18, 27] ;[27, 35]

inversé avec splice = [27, 8] ;[18, 9] ;[9, 9] ;[0, 9]

Code:

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

Vous pouvez essayer ceci pour convertir en colonnes.

CSS :

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

div.clr {
    clear:both;
}

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top