Skip to main content
Gremorie
Containers

Aspect Ratio

Reserve espaço vertical responsivo para que a mídia nunca cause layout shift.

Visão geral

AspectRatio é um primitive de layout de uma prop que trava uma box em uma proporção numérica em qualquer largura de viewport. Coloque-o ao redor de qualquer imagem, iframe, embed de vídeo ou skeleton e o layout ao redor reserva o slot certo antes do asset pintar, eliminando os hits de Cumulative Layout Shift.

Recorra ao AspectRatio sempre que a altura de um filho for derivada de sua largura: covers de hero, thumbnails de card, vídeo estilo oEmbed, iframes de mapa, previews de imagem OG. Para mídia de pixel fixo ou skeletons de curta duração onde você já conhece ambas as dimensões, CSS puro basta.

Preview

16 : 9
'use client';import { AspectRatio } from '@gremorie/rx-containers';export function AspectRatioPreview() {  return (    <div className="max-w-md">      <AspectRatio ratio={16 / 9} className="bg-muted">        <div className="flex h-full w-full items-center justify-center text-sm text-muted-foreground">          16 : 9        </div>      </AspectRatio>    </div>  );}

Anatomia

AspectRatio   box cuja altura é derivada de sua largura e da prop `ratio`; seu filho a preenche (`h-full w-full object-cover`)

Instalação

bash npx gremorie@latest add rx-aspect-ratio

bash pnpm dlx gremorie@latest add rx-aspect-ratio

bash yarn dlx gremorie@latest add rx-aspect-ratio

bash bunx --bun gremorie@latest add rx-aspect-ratio

Uso

import { AspectRatio } from "@gremorie/rx-containers";

export function Cover() {
  return (
    <AspectRatio ratio={16 / 9} className="bg-muted">
      <img
        src="/cover.jpg"
        alt="Cover artwork"
        className="size-full rounded-md object-cover"
      />
    </AspectRatio>
  );
}

A edição Angular deste componente hoje é entregue a partir do código-fonte (veja o workbench para o comparativo lado a lado); a entrada de registry vem em seguida.

API

<AspectRatio>

Renderiza um <div> estilizado pelo Radix para manter width / height = ratio em qualquer breakpoint. O elemento filho deve se dimensionar com size-full (ou width: 100%; height: 100%) para preencher a box reservada.

PropTypeDefaultDescription
rationumber1Aspect ratio expresso como largura dividida por altura. Use 16 / 9 para vídeo landscape, 4 / 3 para vídeo legado, 1 para quadrado, 3 / 4 para posters em portrait.
asChildbooleanfalseQuando true, mescla as props no único elemento filho via Radix Slot em vez de renderizar um div extra.
...propsReact.ComponentProps<"div">-Atributos padrão de div incluindo className e style.

Composição

  1. <AspectRatio> envolve um único filho e reserva a proporção.
  2. O filho (imagem, iframe, vídeo, skeleton) deve preencher a box reservada: className="size-full object-cover" no <img>, className="size-full" em iframes e vídeos.
  3. Dentro de um Card, coloque o AspectRatio no topo do <CardContent> para que o cover fique rente à borda do card.

O wrapper resolve a matemática via padding-bottom mais posicionamento absoluto. Os filhos renderizam dentro de um contexto empilhado, então overlays absolutos (badges, gradientes) compõem naturalmente sem wrappers extras.

Variações

Cover de vídeo com object-fit

16 : 9 video slot

<AspectRatio ratio={16 / 9} className="overflow-hidden rounded-md bg-muted">
  <img
    src="/poster.jpg"
    alt="Episode 12 poster"
    className="size-full object-cover"
  />
</AspectRatio>

Use object-cover no <img> para recortar as bordas que excedem a proporção reservada. Use object-contain quando a imagem precisar ser visível por completo, mesmo que deixe espaço em branco dentro da box.

Tile de avatar quadrado

1 : 1

<AspectRatio ratio={1} className="rounded-full bg-muted">
  <img src="/avatar.jpg" alt="Mila Tasic" className="size-full object-cover" />
</AspectRatio>

Use ratio={1} mais rounded-full para tiles de avatar que escalam fluidamente dentro de células de grid.

Placeholder de skeleton

<AspectRatio ratio={16 / 9} className="rounded-md">
  <Skeleton className="size-full" />
</AspectRatio>

Use o mesmo ratio no skeleton de carregamento e no asset final para que haja zero layout shift quando o asset pintar. Veja Skeleton.

Acessibilidade

  • Apenas apresentação: AspectRatio é um primitive de layout e não renderiza nenhum role próprio. Qualquer semântica pertence ao filho (<img>, <iframe>, <video>).
  • Sempre rotule a mídia: passe um alt real para imagens, um title para iframes e aria-label para vídeos. alt="" vazio só é aceitável para covers decorativos que acompanham texto adjacente.
  • Sem superfície de teclado: o wrapper não é focável. Filhos focáveis (links, controles de vídeo) mantêm sua ordem de tabulação nativa.
  • Nenhum movimento injetado: o primitive não adiciona nenhuma animação, então usuários com prefers-reduced-motion veem o que quer que o filho renderize.

Relacionados

  • Card - o host mais comum para um cover em AspectRatio.
  • Skeleton - combine com AspectRatio para reservar espaço durante o fetch.
  • ScrollArea - primitive irmão para faixas de mídia com scroll horizontal.

On this page