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 umoptionem 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.mediaapenas 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-linkem 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: 1para 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-indexa 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.