KDS
Containers

AspectRatio

Reserva proporção para imagens, embeds e placeholders — antídoto para CLS.

Overview

AspectRatio reserva uma proporção fixa em pixels antes do conteúdo carregar. É o antídoto contra Cumulative Layout Shift (CLS) em imagens responsivas, embeds (YouTube/Vimeo), e placeholders de skeleton — quando o asset chega, ele entra no espaço já reservado, sem empurrar o restante da página.

A escolha do ratio é semântica:

RatioUso típico
16/9Hero de blog, embed de vídeo, OG image.
4/3Foto clássica, screenshot mais alto.
1/1Avatar grande, OG quadrado, NFT-style cards.
3/4Pôster de filme, vertical photography.

Veja [[ui/layout/cumulative-layout-shift]] para a fundamentação do CLS e como AspectRatio fecha esse buraco.

Preview
Hero 16/9 — proporção reservada antes do conteúdo.
16 / 9 — hero / video

Anatomy

<AspectRatio ratio={16 / 9}>
  <img src="..." className="h-full w-full object-cover" />
</AspectRatio>

A criança ocupa 100% do container — use object-cover em imagens para preservar a proporção sem distorcer.

Subcomponents

ComponenteDescrição
AspectRatioWrapper único. Prop ratio (number, ex.: 16 / 9).

Usage

import { AspectRatio } from "@kalvner/kds/containers/aspect-ratio";
import Image from "next/image";

export function PostHero() {
  return (
    <AspectRatio ratio={16 / 9}>
      <Image
        src="/hero.jpg"
        alt="Capa do post"
        fill
        className="rounded-md object-cover"
      />
    </AspectRatio>
  );
}

Variants

4 / 3
Clássico fotográfico.
4 / 3 — clássico fotográfico
1 / 1
Avatar grande, OG image.
1 / 1 — avatar / OG
3 / 4
Pôster, vertical photo.
3 / 4 — pôster

States

Skeleton placeholder
Espaço reservado durante o carregamento.

Composition

Blog hero
Hero 16/9 acima da headline e do meta.
Hero — 16/9

Engenharia

Por que tokens primitivos vivem dentro de @theme

Como Tailwind v4 e shadcn dividem responsabilidades entre cor crua e intenção semântica.

When to use

  • Imagens responsivas com largura variável e altura derivada (heroes, thumbnails, OG previews).
  • Embeds de iframe — YouTube, Vimeo, Loom, Stripe checkout.
  • Skeleton placeholders para espaços que vão receber mídia.
  • Em qualquer card com média que carregam tarde (lazy / on-scroll).

When not to use

  • Quando o elemento já tem dimensões fixas em pixels (w-32 h-32).
  • Para layouts onde a altura é determinada pelo conteúdo textual (Stack, Grid).
  • Em SVGs inline com viewBox — eles já são intrinsecamente proporcionais.
  • Para charts com altura fixa (ex.: h-64) — Charts já reservam espaço.

Best practices

  • object-cover ou object-contain. Sem isso, imagens esticam para preencher e distorcem.
  • fill no Next Image. Combine <AspectRatio ratio={...}> com <Image fill ...> para Next/Image responsivo.
  • sizes no Next Image. Quando usar fill, sempre forneça sizes ("100vw" ou breakpoint-based) para o browser pré-carregar a versão certa.
  • Skeleton + AspectRatio. Para carregamento de mídia, mostre um Skeleton no slot — não deixe vazio. Vazio pisca ao virar imagem.
  • Aprovado para iframes. YouTube embeds funcionam dentro de AspectRatio sem o hack do padding-top: 56.25%.

Accessibility

ConcernComportamento
SemânticaÉ um <div> puro; herda semântica do conteúdo (img, iframe, video).
Alt textSempre forneça alt na imagem ou title+aria-label no iframe. AspectRatio não substitui isso.
Reduced motionEmbeds com auto-play devem respeitar prefers-reduced-motion no nível do player.
  • [[ui/layout/cumulative-layout-shift]] — fundamentação do CLS.
  • ScrollArea — quando o conteúdo extrapola e precisa scrollar.
  • Card — frequente container ao redor de hero + texto.

On this page