Estilo da lista de criativos

Confira 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 sem uma ordem específica. Mas usamos listas de várias formas na Web. Uma coleção dos próximos shows 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 analisar os diferentes tipos de listas HTML disponíveis na Web e quando usá-las, incluindo alguns atributos com os quais você pode não estar familiarizado. 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) notificam 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

Quando se trata de marcação, temos três opções de elementos de lista diferentes disponíveis para nós:

  • 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 é exibido 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 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 a estilização, como vamos conferir 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 cíclicos. 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 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 cada vez:

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

Há muito mais que podemos investigar com os contadores. O artigo Listas, marcadores e contadores do CSS explica algumas das possibilidades com mais detalhes.

Limitações do estilo ::marker

Há momentos em que queremos 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, podemos querer estilizar nossas listas de uma forma 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 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 estilos de lista visualmente complexos.

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 com o flexbox, o que abre um número maior de possibilidades de alinhamento. Por exemplo, podemos alternar a posição do marcador:

Se estivermos definindo o estilo de uma lista ordenada usando o elemento ::before, também poderemos usar contadores para adicionar nossos 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.

Listar atributos

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 álbuns mais tocados do ano passado, poderemos fazer uma contagem regressiva de 10 para 1. Nós poderíamos usar contadores personalizados para isso e incrementá-los negativamente. Ou podemos simplesmente usar o atributo reversed no HTML. Na minha opinião, faz sentido usar o atributo reversed em vez de incrementar negativamente o contador no CSS, a menos que os contadores sejam apenas 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 álbuns mais tocados em 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.

Observe 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, precisamos ajustar os 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 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á algum 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, em nosso 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 apenas 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 intervalos feios 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 usar o valor deles na propriedade content e não permitem cálculos.

Mas podemos definir o índice do elemento no atributo style do nosso 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 por uma lista de várias formas. 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 de 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 exibir 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, que mostra um menu de tortas com as descrições delas.

Podemos definir uma grade na própria lista e garantir que os termos e as descrições estejam sempre 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