Criar um card

Visão geral

Um card agrupa um conteúdo relacionado ou uma opção. É um padrão visual, não um modelo semântico ou de interação fixo. Portanto, preserve o significado do conteúdo e use a interação nativa que corresponda ao propósito dele.

Diretrizes

Escolha a semântica do conteúdo e a interação dele separadamente:

  • use <article> como a raiz do card, esteja ele vinculado a um destino ou não;
  • use um link nativo para navegação. Quando o card inteiro é um destino, um único link pode envolver o <article> somente se o card não tiver outros elementos interativos (a, button, input, select, textarea).
  • mantenha links e botões para ações independentes como controles nativos separados;
  • use um botão de opção ou uma caixa de seleção com um <label> associado ou um option em um <select> nativo quando o card for uma opção.

Mantenha a mídia, o título, o conteúdo de apoio e as ações em uma ordem de origem significativa. Não use o CSS order para contradizê-la (consulte Layouts CSS e design responsivo).

Implementação

Mantenha a marcação mínima e permita que os seletores de CSS reconheçam cada região. Assim, os cards simples continuam simples, e os Rich Cards continuam sendo possíveis. Um card tem até quatro regiões, nesta ordem de origem, e qualquer uma delas pode ser omitida. As regiões são filhas diretas do card, não agrupadas em elementos de wrapper, como .card__body, o que impede a colocação e a estilização de regiões por seletor. Uma região com um único elemento é o próprio elemento, não encapsulado: um parágrafo isolado é o <p>. Use um wrapper somente quando uma região tiver vários elementos.

  • Mídia: um <img>, <picture>, <video> ou <svg> como o primeiro filho. Adicione uma classe .media apenas a conteúdo hero arbitrário que não seja um desses elementos e nunca envolva um <img> simples em um elemento .media.
  • Cabeçalho: um título por si só. Use <hgroup> somente quando o cabeçalho tiver um subtítulo ou slogan e <header> quando a região tiver mais do que um título, como uma assinatura ou um selo. Quando o card tem um destino principal, o link fica dentro do título.
  • Conteúdo: um único <p>, <ul> ou <dl> é suficiente. Quando o conteúdo tiver vários elementos, como vários parágrafos ou um parágrafo e uma lista, agrupe-os em um <div> para que a região seja um único item de grade.
  • Rodapé: um <footer> que contém ações independentes como links e botões nativos. Um link "leia mais" pode compartilhar o URL do link do título, mas dar a ele um nome acessível descritivo que comece com o texto visível, usando texto visualmente oculto (por exemplo, Read more<span> about poached eggs</span>), porque links "leia mais" idênticos são ambíguos na lista de links de um leitor de tela. Não adicione outros links de rodapé que repitam o URL do título.

O card mais simples é um <article> que contém um título e um parágrafo. Escolha o padrão de link e ação que corresponde ao comportamento do card. Consulte Modelos de interação.

Para imagens ou vídeos de card que devem preencher uma área de proporção fixa, defina aspect-ratio e object-fit: cover no próprio <img> ou <video> para que preencham a área sem distorção (pode ocorrer corte). Use o aspect-ratio de um contêiner .media apenas para outro conteúdo hero. Caso contrário, preserve a proporção intrínseca da mídia. Dê às imagens informativas um texto alternativo apropriado. Use alt="" para imagens decorativas.

Adaptar ao espaço disponível

Baseie o layout no espaço disponível do card, não na janela de visualização. Para adaptar os descendentes do card (mídia, texto, ações), defina o card como o contêiner de tamanho (container-type: inline-size) e escreva regras @container para os filhos dele. Evite dimensionar com base na grade ou na lista pai: a largura real do card pode depender da contagem de colunas, de lacunas etc., o que torna os pontos de interrupção baseados no pai ruidosos.

Em um contêiner estreito, empilhe as regiões na ordem de origem. Em um contêiner amplo, coloque a mídia em uma coluna lateral ao lado das outras regiões, mas apenas para cards que tenham mídia: defina o escopo dessas regras com :has() no filho de mídia (por exemplo, .card:has(> img)) para que as definições de coluna e os posicionamentos de grid-column nunca sejam aplicados a um card sem mídia. Um card sem mídia permanece em uma única coluna em todas as larguras e não pode reservar uma coluna de mídia vazia.

Alinhar cards em uma grade

Quando os cards em uma linha precisam compartilhar as alturas das regiões, use subgrid: faça com que cada card ocupe quatro faixas de linha compartilhadas (mídia, cabeçalho, conteúdo, rodapé) e coloque as regiões por seletor de elemento, tratando tudo o que não é mídia, um cabeçalho ou um <footer> como conteúdo. Um card que omite uma região deixa a faixa vazia, de modo que as regiões restantes ainda se alinham com os cards vizinhos. Cada faixa contém um item de grade. Portanto, envolva a região de conteúdo em um <div> somente quando ela tiver mais de um elemento e os cards compartilharem faixas. Os cards que não estão alinhados com os irmãos não precisam de wrapper nem de subgrade.

Modelos de interação

Cards de conteúdo

Use um <article> como raiz do card. Mantenha links e botões como controles nativos separados.

Cartões de destino único

Quando o card inteiro é um destino e não tem ações independentes, use um link nativo. O link pode envolver o <article>. Não aninhe outros links, botões ou controles de formulário no link e mantenha qualquer texto "leia mais" como um <p> ou <span> simples. Como o nome acessível do link é todo o texto do card, mantenha o conteúdo curto. Se o card tiver muito texto ou outras ações, use o padrão de link estendido abaixo para que apenas o título seja o link:

<a href="/recipes/poached-eggs">
  <article class="card">
    <h3>Poached eggs</h3>
    <p>Two poached eggs served on toasted sourdough.</p>
  </article>
</a>

Cards clicáveis com ações independentes

Se o clique no card acionar uma ação em vez de navegar, use um <button> em vez de um link.

Quando um card de conteúdo direciona para um destino principal, também contém outros elementos interativos e precisa ser clicável como um todo:

  • Use uma única ativação no próprio link principal: coloque .card-link em exatamente um link por card (o link do título). O rodapé e outros links nunca recebem o foco, ou cada um deles estenderia a própria sobreposição, e o último capturaria todo o card.
  • Vincule o título e estenda a área de clique do ponteiro pelo card com ::after.
.card:has(a.card-link) {
    position: relative;
}

.card a.card-link::after {
    content: "";
    position: absolute;
    inset: 0;
}
  • Eleve os elementos interativos com position: relative; z-index: 1 para que eles permaneçam operáveis. Segmente tipos de elementos (por exemplo, a, button) em vez de exigir a ativação por classes.
  • NÃO aplique z-index a contêineres inteiros, porque isso faria com que eles capturassem eventos de ponteiro que não produzem nenhuma ação.
.card:has(a.card-link) {
    /* Keep other interactive elements above the overlay */
    a:not(.card-link), button, input, x-button {
        position: relative;
        z-index: 1;
    }
}
  • Estilize o próprio card ao passar o cursor/focar, em vez do link estendido:
.card {
    a.card-link {
        &:focus-visible {
            outline: none; /* Draw it on the card instead */
        }
    }
    
    &:has(a.card-link:focus-visible) {
        /* Focus ring */
    }

    &:has(a.card-link:hover) {
        /* Hover styles */
    }
}

Cartões de escolha

Para cards que representam escolhas predefinidas, use <label class="card"> com uma caixa de seleção ou um botão de opção como filho direto.

Estilize o card selecionado com :has(:checked). Nunca mude as propriedades que afetam o layout, como border-width, padding ou font-weight, na seleção, porque o card e os vizinhos dele vão pular. Destaque com outline, box-shadow ou uma borda transparente que só muda de cor:

.card {
  border: 2px solid transparent;

  &:has(> :checked) {
    border-color: var(--accent);
  }
}

A caixa de seleção ou o botão de opção visível é um indicador de seleção sem cor, então a mudança de cor por si só é suficiente. Se o controle estiver visualmente oculto (mantenha-o focalizável e na árvore de acessibilidade, nunca display: none), adicione um indicador sem cor que não afete o layout, como um ícone de verificação ou um outline mais espesso.

Quando as opções pertencem a um seletor de menu suspenso com opções dispostas como cards, use um <select> nativo com elementos appearance: base-select e estilize os elementos ::picker(select) e <option> em vez de substituir a seleção por cards <div>. Consulte Layouts personalizados do seletor de seleção para mais detalhes e substitutos.