Destino Dev

Blog

Card responsivo com container queries, nesting e animação passo a passo

Por John Pires · 19 de março de 2026

Por que aprender isso em 2026

O CSS evoluiu muito: container queries, nesting e layers já são parte do fluxo de trabalho moderno. Em 2026, projetos web pedem componentes que se adaptam ao contexto, não só à viewport. Aprender a usar container queries permite construir componentes verdadeiramente responsivos sem hacks de JavaScript ou classes extras.

Além disso, o nesting reduz repetição no CSS, tornando regras mais previsíveis e fáceis de manter. Animações simples aumentam a percepção de qualidade da interface; combinadas com consultas de container, permitem transições naturais entre estados do componente.

Este artigo foca em mostrar como montar um card responsivo: vamos configurar o ambiente, criar um hello world progressivo, depois um mini-projeto com container queries, nesting e animações, e terminar com dicas práticas para evitar erros comuns.

Se você está começando, pense em container queries como uma regra que pergunta: "quanto espaço meu componente tem?" — e ajusta o layout do componente com base nisso, em vez de depender apenas do tamanho da tela inteira.

Configuração do ambiente

Não precisa de ferramentas complexas para experimentar. Um navegador moderno (Chrome 105+, Edge, Safari 16+, Firefox com flags em versões anteriores) já suporta a maior parte do que veremos. Recomendo usar uma stack mínima: um arquivo HTML estático e um arquivo CSS.

Para acelerar o feedback, use Live Server (VS Code) ou um servidor estático simples. Se quiser compilar CSS com nesting via PostCSS, configure o plugin css-nesting ou use um bundler que já suporte a sintaxe nativa. Mas no tutorial mostrarei a sintaxe que já está presente em navegadores modernos quando possível.

Resumo do mínimo necessário:

  • Editor de texto (VS Code recomendado)
  • Navegador atualizado
  • Live Server para recarregamento rápido

Configuração opcional (recomendada para produção): PostCSS com plugin de nesting e autoprefixer para suavizar diferenças entre navegadores.

Hello World progressivo

Aqui vamos criar um card simples e evoluir passo a passo. Primeiro o HTML mínimo e o CSS base sem container queries. Esse é o ponto de partida prático para entender o que mudaremos depois.

HTML mínimo (estrutura do card):

<!-- index.html -->
<div class="card">
  <img class="card__img" src="https://picsum.photos/400/300" alt="foto"/>
  <div class="card__body">
    <h3 class="card__title">Título do card</h3>
    <p class="card__desc">Descrição curta para demonstrar o layout do card.</p>
    <button class="card__cta">Ação</button>
  </div>
</div>

O HTML acima produz um card com imagem, título, descrição e botão. Agora aplique estilo base para visualizar o componente.

/* base.css - estilo inicial */
.card{
  border-radius:8px;
  overflow:hidden;
  box-shadow:0 6px 18px rgba(0,0,0,0.08);
  background:#fff;
  width:320px; /* ponto de partida fixo */
  font-family:system-ui,Segoe UI,Roboto,Arial;
}
.card__img{display:block;width:100%;height:auto}
.card__body{padding:16px}
.card__title{margin:0 0 8px;font-size:18px}
.card__desc{margin:0 0 12px;color:#444}
.card__cta{padding:8px 12px;border:none;background:#0069ff;color:#fff;border-radius:6px;cursor:pointer}

O que acontece: com esse CSS o card fica visualmente aceitável, mas não é responsivo ao seu container: se eu colocar dois cards lado a lado ou reduzir o espaço disponível, o layout não muda. A etapa seguinte é transformar esse comportamento para depender do espaço do próprio card.

Evoluindo: enable container

Para permitir consultas ao próprio tamanho do componente, marque o container no CSS. Use container-type e (opcional) container-name. Assim o card passa a ser uma referência para @container.

/* container-enable.css */
.card{
  container-type: inline-size; /* permite consultas relativas à largura do container */
  container-name: card; /* nome legível para usar em @container */
}

Depois dessa declaração, podemos usar @container (ou @container card) para aplicar regras com base na largura do card.

Exemplo básico de container query

Vamos mudar a disposição do card quando ele tiver largura maior que 480px: trocamos empilhamento por layout em grade com imagem à esquerda.

/* container-layout.css */
@container (min-width:480px){
  .card{display:flex;align-items:stretch}
  .card__img{width:40%;height:auto;object-fit:cover}
  .card__body{padding:20px}
}

O que acontece: em contêineres estreitos o card mantém layout vertical; quando o card recebe largura suficiente (por exemplo inserido em uma coluna maior), ele vira um layout horizontal. Observe que isso funciona sem olhar para a viewport, apenas para o espaço que o card ocupa.

Mini-projeto prático: Card responsivo com nesting, layers e animação

Agora montamos um mini-projeto completo. O objetivo: um card que se adapta ao espaço, tem estilos organizados com nesting, usa layers para controle de prioridade e animação suave ao trocar para o layout horizontal.

Estratégia passo a passo:

  1. Definir camada base com @layer para separar reset, componentes e utilities.
  2. Habilitar o container no .card.
  3. Usar nesting para organizar regras do card.
  4. Definir keyframes e transições para animar mudanças de layout.

HTML usado (o mesmo do Hello World, repetido para contexto):

<div class="card">
  <img class="card__img" src="https://picsum.photos/600/400" alt="foto"/>
  <div class="card__body">
    <h3 class="card__title">Título do card</h3>
    <p class="card__desc">Descrição curta para demonstrar o layout do card com container queries e animação.</p>
    <button class="card__cta">Ação</button>
  </div>
</div>

Agora o CSS completo do mini-projeto (note uso de layers, nesting e container queries):

/* projeto.css */
@layer reset, base, components;

@layer reset{
  *,*::before,*::after{box-sizing:border-box}
  body{margin:0;background:#f6f7fb}
}

@layer base{
  .container{max-width:1100px;margin:32px auto;padding:0 16px}
}

@layer components{
  .card{
    container-type:inline-size;
    container-name:card;
    border-radius:12px;
    overflow:hidden;
    background:#fff;
    box-shadow:0 8px 30px rgba(9,30,66,0.08);
    width:320px;
    transition:transform .25s ease,box-shadow .25s ease;

    &__img{display:block;width:100%;height:auto;transition:transform .35s ease}
    &__body{padding:16px}
    &__title{margin:0 0 8px;font-size:18px}
    &__desc{margin:0 0 12px;color:#444}
    &__cta{appearance:none;padding:10px 14px;border-radius:8px;background:#0d6efd;color:#fff;border:none;cursor:pointer}

    /* animação ao flutuar */
    &:hover{transform:translateY(-6px);box-shadow:0 18px 40px rgba(9,30,66,0.12)}
  }

  /* Layout horizontal quando o card tem espaço */
  @container (min-width:520px){
    .card{
      display:flex;gap:0;
      &__img{width:44%;height:100%;object-fit:cover}
      &__body{padding:20px}
    }
  }

  /* Animação que suaviza transição entre empilhado e horizontal */
  @keyframes slideUp{from{transform:translateY(8px);opacity:0}to{transform:none;opacity:1}}
  @container (min-width:520px){
    .card{animation:slideUp .28s ease both}
  }
}

O que acontece: dividimos estilos em layers para garantir previsibilidade. O nesting reduz repetição em selectors (ex.: .card &__img). A declaração container-type permite @container reagir ao espaço do .card. A animação é acionada quando a consulta de container é verdadeira, suavizando a troca para o layout horizontal.

Trabalhando com prefers-reduced-motion e acessibilidade

Sempre considere usuários que preferem animações reduzidas. Inclua uma regra que anule animações quando prefers-reduced-motion estiver ativa.

/* accessibility.css */
@media (prefers-reduced-motion: reduce){
  .card, .card__img{animation:none!important;transition:none!important}
}

O que acontece: navegadores respeitam essa preferência e desativam animações e transições, melhorando acessibilidade.

Erros comuns, armadilhas e dicas práticas

Nessa seção listo problemas que aparecem ao usar container queries, nesting e animações, e como evitá-los.

Erro 1: esquecer de setar container-type — sem isso @container não funciona. Sempre defina container-type no elemento que você quer consultar.

Erro 2: depender de container-name desnecessariamente — você pode usar @container sem nome quando só existe um contexto claro; nome é útil se houver múltiplos containers aninhados.

Erro 3: usar animações que causam layout thrash — anime transform e opacity, não propriedades como width/height que forçam reflow. No exemplo usamos transform e object-fit para evitar repaints pesados.

Dica:

Teste os cards em diferentes contextos: dentro de uma coluna, dentro de um grid, dentro de um modal. Container queries mudam conforme o espaço real do componente.

Outra armadilha: o nesting que você escreve pode não ser suportado por todos os processadores sem transpile. Para produção, verifique a cadeia de ferramentas (PostCSS, Vite, etc.) e faça testes de compatibilidade.

Recursos para continuar estudando

Próximos passos práticos e fontes confiáveis:

  • Especificação de container queries (W3C) — ler para entender limites semânticos
  • Documentação MDN sobre @container, container-type e container-name
  • Guia de acessibilidade em animações — como respeitar prefers-reduced-motion

Recomendo praticar clonando pequenos componentes e inserindo-os em diferentes layouts: cards em grid, sidebar, e em um layout de artigo. O comportamento isolado do componente é o que diferencia um bom uso de container queries.

Ferramentas úteis:

  1. PostCSS (plugin css-nesting) — para compatibilidade de nesting se necessário.
  2. Can I Use — para checar suporte entre navegadores.
  3. Playground do CSS (CodePen/JSFiddle) — para testes rápidos com múltiplas variantes.

Conclusão prática

Você viu um caminho direto: começar com um card estático, habilitar container queries, organizar regras com nesting e layers, e adicionar animações que melhoram a sensação de qualidade. Cada técnica resolve uma dor específica: container queries tornam componentes conscientes do contexto; nesting limpa e reduz repetição; layers trazem previsibilidade na ordem das regras; animações bem escolhidas melhoram percepção sem comprometer performance.

Próxima tarefa prática: pegue três componentes (card, badge, lista) e transforme cada um para usar container queries, testando-os em três widths diferentes. Observe como o comportamento segue o espaço local e não a viewport inteira.

Resumo final: trabalhe de forma incremental, valide em navegadores reais e adicione fallbacks (prefers-reduced-motion, PostCSS) para garantir robustez. Code mais, fale menos: experimente os trechos fornecidos e ajuste para suas necessidades.

Se quiser, posso gerar um projeto ZIP com os arquivos HTML/CSS completos prontos para rodar no Live Server.

Assuntos: CSS, container-queries, nesting, animation, css-layout

Leia também