Estilo da lista de criativos

Confira algumas maneiras úteis e criativas de estilizar uma lista.

Michelle Barker
Michelle Barker

O que vem à mente quando você pensa em uma lista? O exemplo mais óbvio é uma lista de compras, a mais simples das listas, uma coleção de itens sem ordem específica. Mas usamos listas de várias maneiras na Web. Uma coleção de shows futuros em um local? Muito provavelmente uma lista. Um processo de agendamento com várias etapas? Provavelmente uma lista. Uma galeria de imagens? Isso também pode ser considerado uma lista de imagens com legendas.

Neste artigo, vamos nos aprofundar nos diferentes tipos de listas HTML disponíveis na Web e quando usá-las, incluindo alguns atributos que você talvez não conheça. Também vamos conferir algumas maneiras úteis e criativas de definir o estilo delas com CSS.

Quando usar uma lista

Um elemento de lista HTML precisa ser usado quando os itens precisam ser agrupados semanticamente. As tecnologias adaptativas (como leitores de tela) vão notificar o usuário de que há uma lista e o número de itens. Se você pensar em uma grade de produtos em um site de compras, saber essas informações será muito útil. Portanto, usar um elemento de lista pode ser uma boa escolha.

Listar tipos

No caso da marcação, temos três elementos de lista diferentes disponíveis:

  • Lista não ordenada
  • Lista ordenada
  • Lista de descrições

A escolha depende do caso de uso.

Lista não ordenada (ul)

O elemento de lista não ordenada (<ul>) é mais útil quando os itens na lista não correspondem a uma ordem específica. Por padrão, isso vai aparecer como uma lista com marcadores. Um exemplo é uma lista de compras, em que a ordem não importa.

Uma lista de compras de itens como pão, leite e maçãs.

Um exemplo mais comum na Web é um menu de navegação. Ao criar um menu, é recomendável agrupar o ul em um elemento nav e identificar o menu com um rótulo para ajudar as tecnologias adaptativas. Também precisamos identificar a página atual no menu, o que pode ser feito usando o atributo aria-current:

<nav aria-label="Main">  
  <ul>  
    <li>  
      <a href="/page-1" aria-current="page">Menu item 1</a>  
    </li>  
    <li>  
      <a href="/page-2">Menu item 2</a>  
    </li>  
    <li>  
      <a href="/page-2">Menu item 2</a>  
    </li>  
      …  
    </ul>  
</nav>  

Este artigo sobre a estrutura de menus descreve várias recomendações para garantir que os menus de navegação sejam acessíveis a todos.

Lista ordenada (ol)

Um elemento de lista ordenada (<ol>) é a melhor escolha quando a ordem dos itens é importante, como em um processo de várias etapas. Por padrão, os itens da lista são numerados. Um exemplo pode ser um conjunto de instruções, em que as etapas precisam ser concluídas em ordem.

Uma lista detalhando as etapas necessárias para fazer chá com leite.

Os elementos <ol> e <ul> só podem conter elementos <li> como filhos diretos.

Lista de descrições (dl)

Uma lista de descrições contém termos (elementos <dt>) e descrições (<dd>). Cada termo pode ser acompanhado por mais de uma descrição. Os possíveis casos de uso podem incluir um glossário de termos ou talvez um cardápio de restaurante. Por padrão, as listas de descrição não são exibidas com marcadores, embora os navegadores tendam a recuar o elemento <dd>.

No HTML, é permitido agrupar termos com as descrições correspondentes usando um <div>. Isso pode ser útil para estilizar, como veremos mais adiante.

<!-- This is valid --> 
<dl>  
    <dt>Term 1</dt>  
    <dd>This is the first description of the first term in the list</dd>  
    <dd>This is the second description of the first term in the list</dd>  
    <dt>Term 2</dt>  
    <dd>This is the description of the second term in the list</dd>  
</dl>

<!-- This is also valid --> 
<dl>  
    <div>  
        <dt>Term 1</dt>  
        <dd>This is the first description of the first term in the list</dd>  
        <dd>This is the second description of the first term in the list</dd>  
    </div>  
    <div>  
        <dt>Term 2</dt>  
        <dd>This is the description of the second term in the list</dd>  
    </div>  
</dl>  

Estilo de lista simples

Um dos usos mais simples de uma lista é em um bloco de corpo do texto. Muitas vezes, essas listas simples não precisam de um estilo elaborado, mas podemos querer personalizar os marcadores de uma lista ordenada ou não ordenada até certo ponto, como com uma cor da marca ou usando uma imagem personalizada para os marcadores. Podemos fazer muito com list-style e o pseudoelemento ::marker.

::marker

Além de dar um estilo básico aos marcadores de lista, podemos criar marcadores de lista circulares. Aqui, estamos usando três URLs de imagem diferentes para o valor content do pseudoelemento ::marker, o que aumenta a sensação de escrita à mão da nossa lista de compras (em vez de usar apenas uma imagem para todos):

::marker {  
    content: url("/marker-1.svg") ' ';  
}

li:nth-child(3n)::marker {  
    content: url("/marker-2.svg") ' ';  
}

li:nth-child(3n - 1)::marker {  
    content: url("/marker-3.svg") ' ';  
}  

Contadores personalizados

Para algumas listas ordenadas, talvez seja necessário usar o valor do contador, mas anexar outro valor a ele. Podemos usar o contador list-item como um valor para a propriedade content do marcador e anexar qualquer outro conteúdo:

::marker {  
    content: counter(list-item) '🐈 ';  
}  

Nossos contadores incrementam automaticamente em um, mas podemos permitir que eles incrementem em um valor diferente, se quisermos, definindo a propriedade counter-increment no item da lista. Por exemplo, isso vai incrementar nossos contadores em três a cada vez:

li {  
    counter-increment: list-item 3;  
}  

Há muito mais a se aprofundar com os contadores. O artigo Listas, marcadores e contadores do CSS explica algumas das possibilidades com mais detalhes.

Limitações do estilo ::marker

Às vezes, queremos ter mais controle sobre a posição e o estilo dos marcadores. Não é possível posicionar o marcador usando flexbox ou grade, por exemplo, o que às vezes pode ser uma desvantagem se você precisar de outro alinhamento. O ::marker expõe um número limitado de propriedades CSS para estilização. Se o design exigir algo além do estilo básico, talvez seja melhor usar outro pseudoelemento.

Aplicar estilos a listas que não se parecem com listas

Às vezes, queremos estilizar nossas listas de uma maneira totalmente diferente do estilo padrão. Esse é geralmente o caso de um menu de navegação, por exemplo, em que geralmente queremos remover todos os marcadores e mostrar a lista horizontalmente usando flexbox. Uma prática comum é definir a propriedade list-style como none. Isso significa que o pseudoelemento do marcador não será mais acessível no DOM.

Marcadores personalizados com ::before

Antes do ::marker, era comum usar estilos no pseudoelemento ::before para criar marcadores de lista personalizados. Mas, mesmo assim, ele pode oferecer mais flexibilidade, quando necessário, para estilizar listas visualmente complexas.

Assim como ::marker, podemos adicionar nossos próprios estilos de marcadores personalizados usando o atributo content. Ao contrário do uso de ::marker, precisamos fazer um posicionamento manual, já que não temos os benefícios automáticos oferecidos por list-style-position. Mas podemos posicioná-lo com relativa facilidade usando o flexbox, e isso abre um número maior de possibilidades de alinhamento. Por exemplo, podemos alternar a posição do marcador:

Se estivermos estilizando uma lista ordenada usando o elemento ::before, também podemos usar contadores para adicionar marcadores numéricos.

li::before {  
  counter-increment: list-item;  
  content: counter(list-item);  
}  

O uso de ::before em vez de ::marker permite acesso total às propriedades CSS para estilos personalizados, além de permitir animações e transições, para as quais o suporte é limitado para ::marker.

Atributos de lista

Os elementos de listas ordenadas aceitam alguns atributos opcionais, que podem nos ajudar em vários casos de uso.

Listas invertidas

Se tivermos uma lista dos 10 melhores álbuns do ano passado, podemos fazer uma contagem regressiva de 10 a 1. Poderíamos usar contadores personalizados para isso e incrementá-los negativamente. Ou podemos simplesmente usar o atributo reversed no HTML. Eu diria que, em geral, faz sentido semanticamente usar o atributo reversed em vez de incrementar negativamente o contador no CSS, a menos que os contadores sejam puramente de apresentação. Se o CSS não carregar, os números ainda vão aparecer corretamente no HTML. Além disso, precisamos considerar como um leitor de tela interpretaria a lista.

Confira esta demonstração dos 10 principais álbuns de 2021. Se os contadores fossem incrementados apenas com CSS, alguém que acessasse a página usando um leitor de tela poderia concluir que os números foram contados de forma crescente, de modo que o número 10 seria o número 1.

Na demonstração, você pode ver que, ao usar o atributo reversed, nossos marcadores já têm o valor correto, sem nenhum esforço extra da nossa parte. No entanto, se estivermos criando marcadores de lista personalizados usando o pseudoelemento ::before, precisamos ajustar os contadores. Só precisamos instruir o contador de itens da lista para incrementar negativamente:

li::before {  
  counter-increment: list-item -1;  
  content: counter(list-item);  
}  

Isso será suficiente no Firefox, mas no Chrome e no Safari, os marcadores vão contar de zero para -10. Para corrigir isso, adicione o atributo start à lista.

Dividir listas

O atributo start permite especificar o valor numérico em que a lista deve começar. Uma maneira de usar isso é quando você quer dividir uma lista em grupos.

Vamos usar o exemplo dos 10 álbuns mais ouvidos. Talvez você queira contar os 20 melhores álbuns, mas em grupos de 10. Entre os dois grupos, há outro conteúdo da página.

Uma lista em wireframe com colunas e um elemento que atravessa as colunas no meio.

Vamos precisar criar duas listas separadas no HTML, mas como podemos garantir que os contadores estejam corretos? No momento, nossa marcação faz com que as duas listas contem de 10 a 1, o que não é o que queremos. No entanto, no HTML, podemos especificar um valor de atributo start. Se adicionarmos um valor de start igual a 20 à nossa primeira lista, os marcadores serão atualizados automaticamente novamente.

<ol reversed start="20">  
  <li>...</li>  
  <li>...</li>  
  <li>...</li>  
</ol>  

Layout de lista com várias colunas

O layout de várias colunas às vezes pode ser útil para nossas listas, como você pode ver nas demonstrações anteriores. Ao definir uma largura de coluna, podemos garantir que a lista seja responsiva automaticamente, sendo exibida sobre duas ou mais colunas somente quando houver espaço suficiente. Também é possível definir um intervalo entre as colunas e, para dar um toque especial, adicionar uma coluna-regra estilizada (usando uma abreviação semelhante à propriedade border):

ol {  
    columns: 25rem;  
    column-gap: 7rem;  
    column-rule: 4px dotted turquoise;  
}  

Ao usar colunas, às vezes podemos acabar com interrupções feias nos itens da lista, o que não é sempre o efeito desejado.

Uma demonstração de como o conteúdo é dividido entre duas colunas.

Podemos evitar essas pausas forçadas usando break-inside: avoid nos itens da lista:

li {  
    break-inside: avoid;  
}  

Propriedades personalizadas

As propriedades personalizadas do CSS abrem uma gama de possibilidades para estilizar listas. Se soubermos o índice do item da lista, podemos usá-lo para calcular os valores da propriedade. No momento, não há como determinar o índice do elemento (de forma utilizável) no CSS. Os contadores só permitem o uso do valor deles na propriedade content, e não permitem cálculos.

Mas é possível definir o índice do elemento no atributo style no HTML, o que pode tornar os cálculos mais viáveis, especialmente se estivermos usando uma linguagem de modelos. Este exemplo mostra como definir isso usando Nunjucks:

<ol style="--length: items|length">  
  
</ol>  

Splitting.js é uma biblioteca que executa uma função semelhante no lado do cliente.

Usando o valor da propriedade personalizada, podemos mostrar a progressão em uma lista de várias maneiras. Uma maneira de fazer isso é usar uma barra de progresso para uma lista de etapas. Neste exemplo, usamos um pseudoelemento com um gradiente linear para criar uma barra para cada item que mostra o progresso do usuário na lista.

li::before {  
    --stop: calc(100% / var(--length) * var(--i));  
    --color1: deeppink;  
    --color2: pink;  

    content: '';  
    background: linear-gradient(to right, var(--color1) var(--stop), var(--color2) 0);  
}  

Também é possível ajustar a matiz à medida que a lista avança usando a função de cor hsl(). Podemos calcular o valor hue usando nossa propriedade personalizada.

Estilo da lista de descrições

Como mencionado anteriormente, podemos agrupar termos e definições em um div em um dl para ter mais opções de estilo. Por exemplo, podemos querer mostrar nossa lista como uma grade. Definir display: grid na lista sem um wrapper div em cada grupo significa que os termos e as descrições são colocados em células diferentes da grade. Às vezes, isso é útil, como no exemplo a seguir, mostrando um menu de tortas com as descrições.

Podemos definir uma grade na lista e garantir que os termos e as descrições sempre sejam alinhados em colunas, com a largura da coluna determinada pelo termo mais longo.

Por outro lado, se quisermos agrupar termos com descrições de forma distinta, um wrapper <div> é muito útil.

Recursos