Estilo da lista de criativos

Algumas maneiras úteis e criativas de estilizar uma lista.

Michelle Barker
Michelle Barker

O que vem à sua 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 em nenhuma ordem específica. Mas usamos listas de todas as formas na web. Uma coleção dos próximos shows em um local? Muito provavelmente, é uma lista. Um processo de agendamento em várias etapas? Pode ser uma lista. Uma galeria de imagens? Até mesmo isso poderia ser considerado uma lista de imagens com legendas.

Neste artigo, analisaremos os diferentes tipos de listas de HTML disponíveis na Web e quando usá-los, incluindo alguns atributos que você talvez não conheça. Também veremos algumas maneiras úteis e criativas de estilizá-las com CSS.

Quando usar uma lista

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

Listar tipos

Quando se trata de marcação, podemos escolher entre três elementos de lista diferentes:

  • 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 da lista não correspondem a uma ordem específica. Por padrão, ela é exibida 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 envolver a ul em um elemento nav e identificar o menu com um rótulo para ajudar nas 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 dos menus descreve várias recomendações para garantir que nossos menus de navegação sejam acessíveis a todos.

Lista ordenada (ol)

Um elemento de lista ordenado (<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 seria 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> podem conter apenas elementos <li> como filhos diretos.

Lista de descrições (dl)

Uma lista de descrições contém termos (<dt> elementos) 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 o cardápio de um restaurante. As listas de descrições não são mostradas com marcadores por padrão, embora os navegadores tendem a recuar o elemento <dd>.

Em HTML, é permitido agrupar termos com as respectivas descrições usando um <div>. Isso pode ser útil para definir o estilo, 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, por exemplo, com uma cor de marca ou usando uma imagem personalizada para os nossos marcadores. Podemos fazer muitas coisas com list-style e o pseudoelemento ::marker.

::marcador

Além de aplicar um estilo básico aos marcadores de lista, podemos criar marcadores cíclicos. Aqui, estamos usando três URLs de imagem diferentes para o valor content do pseudoelemento ::marker, que adiciona à aparência escrita à mão do exemplo da lista de compras (em vez de usar uma única 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, podemos 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 nosso marcador e anexar qualquer outro conteúdo:

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

Nossos contadores são incrementados automaticamente em um, mas podemos permitir que eles aumentem com um valor diferente se quisermos, definindo a propriedade counter-increment no item da lista. Por exemplo, isso incrementa nossos contadores em três a cada vez:

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

Há muito mais que poderíamos nos aprofundar nos contadores. O artigo Listas, marcadores e contadores de CSS explica algumas das possibilidades com mais detalhes.

Limitações de ::estilização de marcadores

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

Definir o estilo de listas que não parecem listas

Às vezes, queremos estilizar nossas listas de uma maneira totalmente diferente do estilo padrão. Isso geralmente acontece com um menu de navegação, por exemplo, em que geralmente queremos remover todos os marcadores e podemos exibir 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 poderá mais ser acessado no DOM.

Marcadores personalizados com ::before

Estilizar o pseudoelemento ::before era uma maneira comum de criar marcadores de lista personalizados antes do surgimento de ::marker. No entanto, até agora, ele oferece mais flexibilidade para criar listas visualmente complexas quando necessário.

Como em ::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 pelo list-style-position. No entanto, é possível posicioná-lo com relativa facilidade com flexbox, e isso abre um número maior de possibilidades de alinhamento. Por exemplo, podemos alternar a posição do marcador:

Se estamos estilizando uma lista ordenada usando o elemento ::before, também podemos usar contadores para adicionar os 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. O suporte é limitado para ::marker.

Listar atributos

Os elementos das listas ordenadas aceitam alguns atributos opcionais, que podem nos ajudar em diversos casos de uso.

Listas invertidas

Se tivermos uma lista dos 10 álbuns mais tocados do último ano, podemos fazer uma contagem regressiva de 10 para 1. Poderíamos usar contadores personalizados para isso e incrementá-los negativamente. Ou podemos simplesmente usar o atributo reversed no HTML. Em geral, faz sentido 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 for carregado, você ainda verá a contagem regressiva correta no HTML. Além disso, precisamos considerar como um leitor de tela interpretaria a lista.

Veja esta demonstração dos 10 álbuns mais tocados de 2021. Se os contadores fossem incrementados puramente com CSS, alguém que acessasse a página usando um leitor de tela poderia concluir que os números contavam para cima, de modo que o número 10 era, na verdade, o número um.

Veja na demonstração 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, precisaremos ajustar nossos contadores. Só precisamos instruir o contador de itens de lista a incrementar negativamente:

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

Isso é suficiente no Firefox, mas no Google Chrome e no Safari os marcadores contam de zero a -10. Podemos corrigir isso adicionando o atributo start à lista.

Dividir listas

O atributo start permite especificar o valor numérico em que a lista deve começar. Isso pode ser útil quando você quiser dividir uma lista em grupos.

Vamos desenvolver nosso exemplo dos 10 melhores álbuns. Talvez a gente queira contar os 20 álbuns mais tocados, mas em grupos de 10. Entre os dois grupos, há outro conteúdo da página.

Uma lista com wireframe em colunas com um elemento abrangendo as colunas até o meio.

Precisamos criar duas listas separadas no HTML, mas como podemos garantir que os contadores estejam corretos? Como nossa marcação está atualmente, ambas as listas vão contar 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 start de 20 à primeira lista, os marcadores serão atualizados automaticamente.

<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 funciona bem com nossas listas, como você viu nas demonstrações anteriores. Ao definir uma largura de coluna, podemos garantir que nossa lista responda automaticamente, dispondo-se em duas ou mais colunas somente quando houver espaço suficiente. Também podemos definir uma lacuna entre as colunas e, para dar mais retoque, adicione uma regra de coluna 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 quebras desagradáveis em nossos itens de lista, nem sempre o efeito que queremos.

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

Podemos evitar esses intervalos forçados usando break-inside: avoid nos itens da lista:

li {  
    break-inside: avoid;  
}  

Propriedades personalizadas

As propriedades personalizadas de CSS oferecem muitas possibilidades para a estilização de listas. Se soubermos o índice do item da lista, poderemos usá-lo para calcular os valores da propriedade. Infelizmente, no momento não é possível determinar o índice do elemento (de forma utilizável, pelo menos) apenas no CSS. Os contadores só permitem usar o valor deles na propriedade content e não permitem cálculos.

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

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

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

Com o valor da propriedade personalizada, podemos mostrar a progressão por uma lista de várias maneiras. Uma delas pode ser uma barra de progresso com uma lista de etapas. Neste exemplo, usamos um pseudoelemento com gradiente linear para criar uma barra para cada item que mostra o quanto o usuário está 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 podemos ajustar a tonalidade à medida que a lista avança, usando a função de cor hsl(). É possível calcular o valor hue usando nossa propriedade personalizada.

Estilo da lista de descrições

Como mencionado anteriormente, é possível unir os termos e as definições deles em um div em um dl para oferecer mais opções de estilo. Por exemplo, podemos mostrar nossa lista como uma grade. Definir display: grid na lista sem um wrapper div em cada grupo faria com que nossos termos e descrições fossem colocados em diferentes células da grade. Às vezes, isso é útil, como no exemplo a seguir, mostrando um cardápio de tortas com as descrições.

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

Por outro lado, se quisermos agrupar termos de forma distinta com o estilo de card de descrição, um wrapper <div> será muito útil.

Recursos