Como exibir uma lista não ordenada em duas colunas?

215

Com o seguinte HTML, qual é o método mais fácil para exibir a lista como duas colunas?

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

Visor desejado:

A B
C D
E

A solução precisa poder funcionar no Internet Explorer.

atp03
fonte
1
Aqui está um exemplo ao vivo de como fazê-lo facilmente no jquery: jsfiddle.net/EebVF/5 Usando este plugin jquery: github.com/fzondlo/jquery-columns - Eu gosto mais disso do que com CSS porque, com a solução CSS, nem tudo está alinhado verticalmente para o topo.
newUserNameHere

Respostas:

371

Navegadores modernos

aproveite o módulo de colunas css3 para dar suporte ao que você está procurando.

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

CSS:

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

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

Navegadores herdados

Infelizmente, para o suporte ao IE, você precisará de uma solução de código que envolva JavaScript e manipulação de domínio. Isso significa que sempre que o conteúdo da lista for alterado, você precisará executar a operação para reordenar a lista em colunas e reimprimir. A solução abaixo usa o jQuery por questões de brevidade.

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

EDITAR:

Conforme indicado abaixo, isso ordenará as colunas da seguinte maneira:

A  E
B  F
C  G
D

enquanto o OP solicitou uma variante correspondente ao seguinte:

A  B
C  D
E  F
G

Para realizar a variante, basta alterar o código para o seguinte:

function updateColumns(){
    column = 0;
    columnItems.each(function(idx, el){
        if (column > columns.length){
            column = 0;
        }
        $(columns.get(column)).append(el);
        column += 1;
    });
}
Gabriel
fonte
2
Você não está exibindo os itens na ordem correta: jsfiddle.net/HP85j/258 Por exemplo, a exibição desejada na primeira linha é A B(o segundo elemento deve ser anexado à direita), mas nos seus exemplos é A E.
Paolo Moretti
1
Bom trabalho, embora a lógica seja falha se houver mais de 2 colunas, eu criei a correção aqui: jsfiddle.net/HP85j/393
Tr1stan
2
as balas estão faltando
Jaider
1
Provavelmente, é mais provável que a lista preencha a coluna 1 antes da coluna 2. Pode ser mais fácil simplesmente reordenar os itens da lista para que pareçam que eles tenham sido preenchidos antes da inatividade. Claro que isso pode exigir refazer se a lista mudar. Enfim, a resposta CSS de Gabriel foi exatamente o que eu precisava, obrigado!
punstress
3
Apenas uma atualização tardia, acredito que a primeira opção agora funcionará nos navegadores modernos do IE.
Fizz
82

Eu estava olhando para a solução da @ jaider, que funcionou, mas estou oferecendo uma abordagem um pouco diferente, que acho mais fácil de trabalhar e que considero ser boa nos navegadores.

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

Por padrão, a lista não ordenada exibe a posição do marcador do lado de fora, mas, em alguns navegadores, isso causa alguns problemas de exibição com base na maneira do navegador de exibir seu site.

Para que seja exibido no formato:

A B
C D
E

etc. use o seguinte:

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

Isso deve resolver todos os seus problemas com a exibição de colunas. Tudo de bom e obrigado @jaider como sua resposta ajudou a me orientar a descobrir isso.

Winnifred
fonte
3
Há um problema com este método. Ele funciona muito bem para exibir itens de lista muito curtos (1 caractere neste exemplo). Crie uma lista com descrições mais longas e a segunda coluna se sobrepõe à primeira, além de ficar sem o contêiner ul.
Shaggy
1
Eu modifiquei isso ligeiramente alterando float: left para display: inline-block para elementos li, além de que isso funcionou maravilhosamente para mim.
ZeRemz 23/06
41

Tentei postar isso como um comentário, mas não consegui exibir as colunas corretamente (conforme sua pergunta).

Você está pedindo:

AB

CD

E

... mas a resposta aceita como solução retornará:

DE ANÚNCIOS

ESTAR

C

... então a resposta está incorreta ou a pergunta está.

Uma solução muito simples seria definir a largura do seu <ul>e, em seguida, flutuar e definir a largura dos seus <li>itens da seguinte maneira

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

Exemplo aqui http://jsfiddle.net/Jayx/Qbz9S/1/

Se sua pergunta estiver errada, as respostas anteriores se aplicam (com uma correção JS por falta de suporte do IE).

Jayx
fonte
@ Gabriel sua solução e o comportamento é bom e conforme o esperado, então não estou tentando responder sua resposta hey ... só acho que a pergunta pode ter sido mal interpretada ... de qualquer maneira - a pergunta foi respondida não importa qual é a pergunta correta: D
Jayx 08/02
16

Gosto da solução para navegadores modernos, mas faltam os marcadores, então adiciono um pequeno truque:

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

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


li:before {
  content: "• ";
}

insira a descrição da imagem aqui

Jaider
fonte
Aqui podemos mudar a cor dos itens sem mudança a cor da bala jsfiddle.net/HP85j/444
Jaider
3
Eu acho que list-style-position: inside;é uma solução melhor para as balas aparecerem corretamente.
Alexis Wilke
11

Aqui está uma solução possível:

Snippet:

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>

E está feito.
Para 3 colunas, use lilargura como 33%, para 4 colunas, use 25% e assim por diante.

Abdul
fonte
5

Esta é a maneira mais simples de fazer isso. Apenas CSS.

  1. adicione largura ao elemento ul.
  2. add display: bloco embutido e largura da nova coluna (deve ser menor que a metade da largura da 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>
Aviv Shaal
fonte
2
Adicione um pouco de explicação com a resposta de como essa resposta ajuda OP na fixação edição atual
ρяσѕρєя K
4

Você pode usar CSS apenas para definir duas colunas ou mais

AE

B

C

D

 <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;
 }
Bouhejba zied
fonte
3

Isso pode ser alcançado usando a propriedade css de contagem de colunas na div pai,

gostar

 column-count:2;

verifique isso para mais detalhes.

Como fazer a lista DIV flutuante aparecer em colunas, não em linhas

maximus ツ
fonte
1
column-countnão exibirá os itens na ordem correta. Por exemplo, a exibição desejada na primeira linha é A B(o segundo elemento deve ser anexado à direita), mas se você o usar column-count, será A E.
Paolo Moretti
2

Você pode fazer isso com muita facilidade com o plug-in jQuery-Columns, por exemplo, para dividir um ul com uma classe de .mylist que você faria

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

Aqui está um exemplo ao vivo no jsfiddle

Eu gosto disso melhor do que com CSS porque, com a solução CSS, nem tudo se alinha verticalmente ao topo.

newUserNameHere
fonte
Interessante, mas na verdade divide a <ul>lista em várias listas ... Isso pode complicar outras coisas.
Alexis Wilke
Na verdade, essa foi a solução que procurava graças ao downvoter. Essa resposta é válida se você ler a pergunta do OP e não houver necessidade de DV.
Tricky
2

mais uma resposta depois de alguns anos!

neste artigo: 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%; }
user3632930
fonte
1

Em updateColumns()necessidade if (column >= columns.length), em vez de if (column > columns.length)para listar todos os elementos (C é saltado por exemplo) de modo a:

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/

Daver
fonte
1

A solução legada na resposta principal não funcionou para mim porque eu queria afetar várias listas na página e a resposta assume uma única lista, além de usar um pouco do estado global. Nesse caso, eu queria alterar todas as listas dentro de um <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]);
    }
});
Tom
fonte
como é possível, por exemplo, gerar duas colunas, uma apenas contém o bloco e a outra uma lista não ordenada?
Dalek
Não tenho certeza do que você quis dizer. Se você tem uma série de itens com títulos, você pode colocá-los em uma única lista com título, item, título, item e, em seguida, isso deve funcionar para você.
Tom
1

Embora eu tenha encontrado a resposta de Gabriel para trabalhar até certo ponto, encontrei o seguinte ao tentar ordenar a lista verticalmente (primeiro ul AD e segundo ul EG):

  • Quando o ul continha um número par de li's, não o espalhava uniformemente pelos
  • usar a coluna de dados no ul não pareceu funcionar muito bem, tive que colocar 4 por 3 colunas e mesmo assim ainda estava espalhando os li's em 2 dos ul gerados pelo JS

Revisei o JQuery para que o que foi dito acima não aconteça.

(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>
Anthony Medhurst
fonte