Existe uma maneira de quebrar uma lista em colunas?

119

Minha página da web tem uma lista 'skinny': por exemplo, uma lista de 100 itens de uma palavra cada. Para reduzir a rolagem, quero apresentar essa lista em duas ou até quatro colunas na página. Como devo fazer isso com CSS?

<ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
</ul>

Prefiro que a solução seja flexível, de modo que, se a lista aumentar para 200 itens, não precise fazer muitos ajustes manuais para acomodar a nova lista.

user776676
fonte
Existe uma biblioteca que faz isso - github.com/yairEO/listBreaker
vsync
Eu acredito que a opção de coluna CSS servirá. Esta opção é fácil de usar e alterar se houver necessidade. Aqui você tem explicado em detalhes - kolosek.com/css-columns
Zoric

Respostas:

254

A solução CSS é: http://www.w3.org/TR/css3-multicol/

O suporte do navegador é exatamente o que você esperaria.

Funciona "em qualquer lugar", exceto no Internet Explorer 9 ou anterior: http://caniuse.com/multicolumn

ul {
    -moz-column-count: 4;
    -moz-column-gap: 20px;
    -webkit-column-count: 4;
    -webkit-column-gap: 20px;
    column-count: 4;
    column-gap: 20px;
}

Veja: http://jsfiddle.net/pdExf/

Se o suporte do IE for necessário, você terá que usar JavaScript, por exemplo:

http://welcome.totheinter.net/columnizer-jquery-plugin/

Outra solução é voltar ao normal apenasfloat: left para o IE . O pedido estará errado, mas pelo menos será semelhante:

Veja: http://jsfiddle.net/NJ4Hw/

<!--[if lt IE 10]>
<style>
li {
    width: 25%;
    float: left
}
</style>
<![endif]-->

Você pode aplicar esse fallback com o Modernizr se já estiver usando.

trinta pontos
fonte
Existe uma maneira de remover a borda superior na primeira lide cada coluna?
Sim Barry
2
Isso funciona muito bem para um espaço fixo, mas se torna um problema com designs responsivos, uma vez que as colunas não se contraem como ao usar display: inline ou inline-block.
unifiedac
4
Fato interessante: o IE é o único navegador de desktop importante a oferecer suporte total a esse recurso sem prefixos (desde o IE10) ... Que ironia ...
NemoStein
1
Pode ser necessário para um melhor suporte para vários navegadores incluir esta propriedade adicional list-style-position: inside; que aborda especificamente o problema apontado por @vsync, acredito.
ThisClark
4
@PrafullaKumarSahu: Experimente li { break-inside: avoid; }: jsfiddle.net/thirtydot/pdExf/903 . Não estou muito familiarizado com colunas CSS, então pode haver uma maneira melhor.
trinta pontos
19

Se você está procurando uma solução que funcione no IE também, você pode flutuar os elementos da lista para a esquerda. No entanto, isso resultará em uma lista que serpenteia, como esta:

item 1 | item 2 | item 3
item 4 | item 5

Em vez de colunas organizadas, como:

item 1 | item 4
item 2 | 
item 3 | 

O código para fazer isso seria:

ul li {
  width:10em;
  float:left;
}

Você pode adicionar uma borda inferior ao lis para tornar o fluxo dos itens da esquerda para a direita mais aparente.

Matt Hampel
fonte
embora possa funcionar para um número específico de itens, o resultado não será bonito para apenas 2 itens.
vsync
Outra solução CSS funcional para as "colunas legais": stackoverflow.com/q/54982323/1066234
Kai Noack
10

Se quiser um número predefinido de colunas, você pode usar contagem de colunas e lacuna de colunas, conforme mencionado acima.

No entanto, se você quiser uma única coluna com altura limitada que se quebraria em mais colunas se necessário, isso pode ser feito simplesmente mudando a exibição para flex.

Isso não funcionará no IE9 e alguns outros navegadores antigos. Você pode verificar o suporte em Posso usar

<style>
  ul {
    display: -ms-flexbox;           /* IE 10 */
    display: -webkit-flex;          /* Safari 6.1+. iOS 7.1+ */
    display: flex;
    -webkit-flex-flow: wrap column; /* Safari 6.1+ */
    flex-flow: wrap column;
    max-height: 150px;              /* Limit height to whatever you need */
  }
</style>

<ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
</ul>

Maciej Poleski
fonte
2
Muito perto do que estou procurando. A única desvantagem é que a largura das colunas não se adapta ao conteúdo (tente com itens de comprimento diferente). Não tenho certeza de como a largura da coluna é definida. Talvez com o primeiro elemento? Em qualquer caso, alguma indicação de como superar isso?
jorgeh
Seria possível limitar o número de colunas em vez da altura? Preciso que os itens sejam preenchidos em quatro colunas, e o css column-countfará um número ímpar de linhas nas colunas. Como 6 itens na primeira coluna, depois 4, depois 6 e depois 5.
Virge Assault
Seria bom se você rotular os itens, por exemplo, "Item 1", "Item 2" para que os visualizadores possam ver o fluxo dos elementos
allkenang,
3

Essa resposta não é necessariamente escalável, mas requer apenas pequenos ajustes conforme a lista cresce. Semanticamente, pode parecer um pouco contra-intuitivo, já que são duas listas, mas, fora isso, terá a aparência que você deseja em qualquer navegador já criado.

ul {
  float: left;
}

ul > li {
  width: 6em;
}
<!-- Column 1 -->
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>
<!-- Column 2 -->
<ul>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
</ul>

Alan Hape
fonte
2

2020 - mantenha a simplicidade, use CSS Grid

Muitas dessas respostas estão desatualizadas, estamos em 2020 e não deveríamos permitir que pessoas que ainda usam o IE9. É muito mais simples usar a grade CSS .

O código é muito simples e você pode ajustar facilmente quantas colunas existem usando o grid-template-columns. Veja isso e brinque com este violino para atender às suas necessidades.

.grid-list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
<ul class="grid-list">
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
</ul>

maxshuty
fonte
1
Esta é a melhor solução para mim.
Patee Gutee
1

Descobri que (atualmente) Chrome ( Version 52.0.2743.116 m) tem toneladas de peculiaridades e problemas com css em column-countrelação a itens de overflow e elementos posicionados absolutos dentro de itens, especialmente com algumas transições de dimensões.

é uma bagunça total e não pode ser consertada, então tentei resolver isso por meio de javascript simples e criei uma biblioteca que faz isso - https://github.com/yairEO/listBreaker

Página de demonstração

vsync
fonte
Eu prefiro o plugin colunizador jQuery, na minha opinião ele tinha melhor funcionalidade para o que eu estava fazendo (era capaz de classificar em ordem alfabética, decrescente ou crescente, contagem de colunas, largura de colunas e muito mais). jQuery Columnizer - WelcomeToTheInter.Net
Brandito
@Brandito - bem, o código do Colunizador com certeza tem mais opções, já que é quase 1.000 linhas de código, em comparação com o meu que tem cerca de 120 linhas .. mas faz o trabalho bem
vsync
sim, mas meu problema precisava que a lista permanecesse como uma lista, o que é mais útil / necessário depende do caso de uso.
Brandito
0

Se você puder, CSS Grid é provavelmente a maneira mais limpa de fazer uma lista unidimensional em um layout de duas colunas com interiores responsivos.

ul {
  max-width: 400px;
  display: grid;
  grid-template-columns: 50% 50%;
  padding-left: 0;
  border: 1px solid blue;
}

li {
  list-style: inside;
  border: 1px dashed red;
  padding: 10px;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
<ul>

Estas são as duas linhas principais que lhe darão o layout de 2 colunas

display: grid;
grid-template-columns: 50% 50%;
mattLummus
fonte
0

A primeira maneira para dispositivos móveis é usar CSS Columns para criar uma experiência para telas menores e, em seguida, usar Media Queries para aumentar o número de colunas em cada um dos pontos de interrupção definidos do layout.

ul {
  column-count: 2;
  column-gap: 2rem;
}
@media screen and (min-width: 768px)) {
  ul {
    column-count: 3;
    column-gap: 5rem;
  }
}
<ul>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
</ul>

Josh Habdas
fonte
0

Aqui está o que eu fiz

ul {
      display: block;
      width: 100%;
}

ul li{
    display: block;
    min-width: calc(30% - 10px);
    float: left;
}

ul li:nth-child(2n + 1){
    clear: left;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>0</li>
</ul>

GuruKay
fonte