Comment afficher une liste non ordonnée sur deux colonnes?


216

Avec le code HTML suivant, quelle est la méthode la plus simple pour afficher la liste sur deux colonnes?

<ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
    <li>E</li>
</ul>

Affichage souhaité:

A B
C D
E

La solution doit pouvoir fonctionner sur Internet Explorer.


1
Voici un exemple en direct de la façon de le faire facilement dans jquery: jsfiddle.net/EebVF/5 Utilisation de ce plugin jquery: github.com/fzondlo/jquery-columns - J'aime mieux cela qu'avec CSS car avec la solution CSS tout ne s'aligne pas verticalement vers le haut.
newUserNameHere

Réponses:


372

Navigateurs modernes

exploitez le module de colonnes css3 pour prendre en charge ce que vous recherchez.

http://www.w3schools.com/cssref/css3_pr_columns.asp

CSS:

ul {
  columns: 2;
  -webkit-columns: 2;
  -moz-columns: 2;
}

http://jsfiddle.net/HP85j/8/

Navigateurs hérités

Malheureusement, pour le support d'IE, vous aurez besoin d'une solution de code qui implique la manipulation de JavaScript et de dom. Cela signifie qu'à chaque fois que le contenu de la liste change, vous devrez effectuer l'opération de réorganisation de la liste en colonnes et de réimpression. La solution ci-dessous utilise jQuery pour plus de concision.

http://jsfiddle.net/HP85j/19/

HTML:

<div>
    <ul class="columns" data-columns="2">
        <li>A</li>
        <li>B</li>
        <li>C</li>
        <li>D</li>
        <li>E</li>
        <li>F</li>
        <li>G</li>
    </ul>
</div>

JavaScript:

(function($){
    var initialContainer = $('.columns'),
        columnItems = $('.columns li'),
        columns = null,
        column = 1; // account for initial column
    function updateColumns(){
        column = 0;
        columnItems.each(function(idx, el){
            if (idx !== 0 && idx > (columnItems.length / columns.length) + (column * idx)){
                column += 1;
            }
            $(columns.get(column)).append(el);
        });
    }
    function setupColumns(){
        columnItems.detach();
        while (column++ < initialContainer.data('columns')){
            initialContainer.clone().insertBefore(initialContainer);
            column++;
        }
        columns = $('.columns');
    }

    $(function(){
        setupColumns();
        updateColumns();
    });
})(jQuery);

CSS:

.columns{
    float: left;
    position: relative;
    margin-right: 20px;
}

ÉDITER:

Comme indiqué ci-dessous, les colonnes seront ordonnées comme suit:

A  E
B  F
C  G
D

tandis que le PO a demandé une variante correspondant à ce qui suit:

A  B
C  D
E  F
G

Pour accomplir la variante, vous changez simplement le code comme suit:

function updateColumns(){
    column = 0;
    columnItems.each(function(idx, el){
        if (column > columns.length){
            column = 0;
        }
        $(columns.get(column)).append(el);
        column += 1;
    });
}

2
Vous n'affichez pas les éléments dans le bon ordre: jsfiddle.net/HP85j/258 Par exemple, l'affichage souhaité dans la première ligne est A B(le deuxième élément doit être ajouté à droite), mais dans vos exemples, c'est A E.
Paolo Moretti

1
Excellent travail, bien que la logique soit défectueuse s'il y a plus de 2 colonnes, j'ai créé le correctif ici: jsfiddle.net/HP85j/393
Tr1stan

2
les balles manquent
Jaider

1
Il est probablement plus probable que la liste remplisse la colonne 1 avant la colonne 2. Il peut être plus facile de simplement réorganiser les éléments de la liste afin qu'il semble qu'ils soient remplis avant la fin. Bien sûr, cela peut nécessiter de refaire si la liste change. Quoi qu'il en soit, la réponse CSS de Gabriel était exactement ce dont j'avais besoin, merci!
punstress

3
Juste une mise à jour tardive, je pense que la première option fonctionnera désormais dans les navigateurs IE modernes.
Fizz

83

Je cherchais la solution de @ jaider qui a fonctionné, mais j'offre une approche légèrement différente avec laquelle je pense qu'il est plus facile de travailler et que j'ai vue être bonne sur tous les navigateurs.

ul{
    list-style-type: disc;
    -webkit-columns: 2;
    -moz-columns: 2;
    columns: 2;
    list-style-position: inside;//this is important addition
}

Par défaut, la liste non ordonnée affiche la position de la puce à l'extérieur, mais dans certains navigateurs, cela entraînerait des problèmes d'affichage en fonction de la façon dont le navigateur présente votre site Web.

Pour l'afficher au format:

A B
C D
E

etc., utilisez les éléments suivants:

ul li{
    float: left;
    width: 50%;//helps to determine number of columns, for instance 33.3% displays 3 columns
}
ul{
    list-style-type: disc;
}

Cela devrait résoudre tous vos problèmes d'affichage des colonnes. Tous mes meilleurs vœux et merci @jaider, car votre réponse m'a aidé à le découvrir.


3
Il y a un problème avec cette méthode. Cela fonctionne très bien pour afficher des éléments de liste très courts (1 caractère dans cet exemple). Créez une liste avec des descriptions plus longues et la deuxième colonne chevauche la première, ainsi que s'exécute hors du conteneur ul.
Shaggy

1
J'ai légèrement modifié cela en changeant float: left pour afficher: inline-block pour les éléments li, à part cela, cela a fait des merveilles pour moi.
ZeRemz

41

J'ai essayé de poster ceci en tant que commentaire, mais je n'ai pas pu afficher les colonnes correctement (selon votre question).

Vous demandez:

UN B

CD

E

... mais la réponse acceptée comme solution reviendra:

UN D

ÊTRE

C

... soit la réponse est incorrecte, soit la question l'est.

Une solution très simple serait de définir la largeur de votre <ul>, puis de flotter et de définir la largeur de vos <li>articles comme suit

<ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
    <li>E</li>
</ul>

ul{
    width:210px;
}
li{
    background:green;
    float:left;
    height:100px;
    margin:0 10px 10px 0;
    width:100px;
}
li:nth-child(even){
    margin-right:0;
}

Exemple ici http://jsfiddle.net/Jayx/Qbz9S/1/

Si votre question est fausse, les réponses précédentes s'appliquent (avec un correctif JS pour manque de support IE).


@Gabriel votre solution et le comportement est bon et comme prévu, donc je n'essaie pas de frapper votre réponse hé ... Je pense juste que la question a peut-être été mal interprétée ... de toute façon - la question a été répondue peu importe quelle est la bonne question: D
Jayx

16

J'aime la solution pour les navigateurs modernes, mais les puces manquent, alors j'ajoute un petit truc:

http://jsfiddle.net/HP85j/419/

ul {
    list-style-type: none;
    columns: 2;
    -webkit-columns: 2;
    -moz-columns: 2;
}


li:before {
  content: "• ";
}

entrez la description de l'image ici


Ici, nous pouvons changer la couleur des articles sans changer la couleur de la balle jsfiddle.net/HP85j/444
Jaider

3
Je pense que list-style-position: inside;c'est une meilleure solution pour que les balles apparaissent correctement.
Alexis Wilke

11

Voici une solution possible:

Fragment:

ul {
  width: 760px;
  margin-bottom: 20px;
  overflow: hidden;
  border-top: 1px solid #ccc;
}
li {
  line-height: 1.5em;
  border-bottom: 1px solid #ccc;
  float: left;
  display: inline;
}
#double li {
  width: 50%;
}
<ul id="double">
  <li>first</li>
  <li>second</li>
  <li>third</li>
  <li>fourth</li>
</ul>

Et c'est fait.
Pour 3 colonnes, utilisez une lilargeur de 33%, pour 4 colonnes, utilisez 25%, etc.


5

C'est la manière la plus simple de le faire. CSS uniquement.

  1. ajouter de la largeur à l'élément ul.
  2. add display: inline-block et largeur de la nouvelle colonne (doit être inférieure à la moitié de la largeur ul).
ul.list {
  width: 300px;  
}

ul.list li{
  display:inline-block;
  width: 100px;
}
<ul class="list">
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
    <li>E</li>
</ul>

2
Ajoutez une explication avec la réponse pour savoir comment cette réponse aide OP à résoudre le problème actuel
ρяσѕρєя K

4

Vous pouvez utiliser CSS uniquement pour définir deux colonnes ou plus

AE

B

C

 <ul class="columns">
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
    <li>E</li>
</ul>

ul.columns  {
   -webkit-columns: 60px 2;
   -moz-columns: 60px 2;
    columns: 60px 2;
   -moz-column-fill: auto;
   column-fill: auto;
 }

3

Cela peut être réalisé en utilisant la propriété css de comptage de colonnes sur div parent,

comme

 column-count:2;

consultez ceci pour plus de détails.

Comment faire apparaître une liste DIV flottante dans des colonnes, pas des lignes


1
column-countn'affichera pas les articles dans le bon ordre. Par exemple, l'affichage souhaité dans la première ligne est A B(le deuxième élément doit être ajouté à droite), mais si vous l'utilisez, column-countil le sera A E.
Paolo Moretti

2

Vous pouvez le faire très facilement avec le plugin jQuery-Columns par exemple pour diviser un ul avec une classe de .mylist que vous feriez

$('.mylist').cols(2);

Voici un exemple en direct sur jsfiddle

J'aime mieux cela qu'avec CSS car avec la solution CSS tout ne s'aligne pas verticalement vers le haut.


Intéressant, mais il décompose en fait la <ul> liste en plusieurs listes ... Cela pourrait compliquer d'autres choses.
Alexis Wilke

C'était en fait la solution que je recherchais, grâce au downvoter, cette réponse est valable si vous lisez la question de l'OP et qu'il n'y a pas besoin de DV.
Tricky

2

plus une réponse après quelques années!

dans cet article: http://csswizardry.com/2010/02/mutiple-column-lists-using-one-ul/

HTML:

<ul id="double"> <!-- Alter ID accordingly -->
  <li>CSS</li>
  <li>XHTML</li>
  <li>Semantics</li>
  <li>Accessibility</li>
  <li>Usability</li>
  <li>Web Standards</li>
  <li>PHP</li>
  <li>Typography</li>
  <li>Grids</li>
  <li>CSS3</li>
  <li>HTML5</li>
  <li>UI</li>
</ul>

CSS:

ul{
  width:760px;
  margin-bottom:20px;
  overflow:hidden;
  border-top:1px solid #ccc;
}
li{
  line-height:1.5em;
  border-bottom:1px solid #ccc;
  float:left;
  display:inline;
}
#double li  { width:50%;}
#triple li  { width:33.333%; }
#quad li    { width:25%; }
#six li     { width:16.666%; }

1

Dans le updateColumns()besoin if (column >= columns.length)plutôt que if (column > columns.length)de lister tous les éléments (C est sauté par exemple) donc:

function updateColumns(){
    column = 0;
    columnItems.each(function(idx, el){
        if (column >= columns.length){
            column = 0;
        }
        console.log(column, el, idx);
        $(columns.get(column)).append(el);
        column += 1;
    });
}

http://jsfiddle.net/e2vH9/1/



1

La solution héritée dans la réponse du haut ne fonctionnait pas pour moi car je voulais affecter plusieurs listes sur la page et la réponse suppose une seule liste et elle utilise un bon état global. Dans ce cas, je voulais modifier chaque liste dans un <section class="list-content">:

const columns = 2;
$("section.list-content").each(function (index, element) {
    let section = $(element);
    let items = section.find("ul li").detach();
    section.find("ul").detach();
    for (let i = 0; i < columns; i++) {
        section.append("<ul></ul>");
    }
    let lists = section.find("ul");
    for (let i = 0; i < items.length; i++) {
        lists.get(i % columns).append(items[i]);
    }
});

comment est-il possible par exemple de générer deux colonnes, l'une ne contient que la tuile et l'autre une liste non ordonnée?
Dalek

Je ne sais pas trop ce que tu veux dire. Si vous avez une série d'éléments avec des titres, vous pouvez les mettre dans une seule liste allant du titre, de l'élément, du titre, de l'élément, puis cela devrait fonctionner pour vous.
Tom

1

Bien que j'ai trouvé la réponse de Gabriel pour travailler à un degré, j'ai trouvé ce qui suit en essayant de classer la liste verticalement (premier ul AD et deuxième ul EG):

  • Lorsque l'ul avait un nombre pair de li, il ne l'étalait pas uniformément sur l'ul
  • l'utilisation de la colonne de données dans le ul ne semblait pas très bien fonctionner, j'ai dû mettre 4 pour 3 colonnes et même alors, cela ne faisait que répartir les li dans 2 des ul générés par le JS

J'ai révisé le JQuery afin que ce qui précède ne se produise pas.

(function ($) {
    var initialContainer = $('.customcolumns'),
        columnItems = $('.customcolumns li'),
        columns = null,
        column = 0;
    function updateColumns() {
        column = 0;
        columnItems.each(function (idx, el) {
            if ($(columns.get(column)).find('li').length >= (columnItems.length / initialContainer.data('columns'))) {
                column += 1;
            }
            $(columns.get(column)).append(el);
        });
    }
    function setupColumns() {
        columnItems.detach();
        while (column++ < initialContainer.data('columns')) {
            initialContainer.clone().insertBefore(initialContainer);
            column++;
        }
        columns = $('.customcolumns');
        updateColumns();
    }

    $(setupColumns);
})(jQuery);
.customcolumns {
  float: left;
  position: relative;
  margin-right: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <ul class="customcolumns" data-columns="3">
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
    <li>E</li>
    <li>F</li>
    <li>G</li>
    <li>H</li>
    <li>I</li>
    <li>J</li>
    <li>K</li>
    <li>L</li>
    <li>M</li>
  </ul>
</div>

-1

Thisd était une solution parfaite pour moi, à la recherche depuis des années:

http://css-tricks.com/forums/topic/two-column-unordered-list/


3
"Citez toujours la partie la plus pertinente d'un lien important, au cas où le site cible serait inaccessible ou se déconnecterait définitivement" - stackoverflow.com/help/how-to-answer
Sk8erPeter

Pas besoin - c'est le lien / référence pour le code utilisé par Abduldans sa réponse, identique à la largeur et à l'ID utilisées.
cssyphus
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.