Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsLayout Blocks

AspectRatio

Constrains content to a specific width/height ratio using CSS aspect-ratio. Seven named presets, arbitrary string or numeric ratios, eight corner-radius presets, automatic object-fit on single media children, and polymorphic render.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import { AspectRatio } from "@tessinaui/ui";
{/* Named preset */}
<AspectRatio ratio="video" rounded="md">
  <img src="/hero.jpg" alt="" />
</AspectRatio>

{/* Custom numeric ratio */}
<AspectRatio ratio={21 / 9}>
  <img src="/panorama.jpg" alt="" />
</AspectRatio>

{/* Arbitrary CSS string */}
<AspectRatio ratio="2.35 / 1">
  <video src="/cinemascope.mp4" />
</AspectRatio>

{/* Object fit on single media children */}
<AspectRatio ratio="square" objectFit="cover">
  <img src="/avatar.jpg" alt="" />
</AspectRatio>

{/* Non-media content */}
<AspectRatio ratio="video" rounded="lg">
  <div className="grid place-items-center bg-primary-light">
    Placeholder
  </div>
</AspectRatio>

{/* Polymorphic — render as a figure */}
<AspectRatio ratio="portrait" render={<figure />}>
  <img src="/photo.jpg" alt="" />
</AspectRatio>

Showcase

Named ratios

Seven opinionated presets cover most common cases.

PresetRatioTypical use
"square"1 / 1Avatars, profile tiles
"video" (default)16 / 9Video thumbnails, hero banners
"portrait"3 / 4Phone-oriented photos
"landscape"4 / 3Classic photography
"ultrawide"21 / 9Panoramas, cinematic headers
"vertical"9 / 16Stories, TikTok, Reels
"golden"1.618 / 1Editorial layouts

Custom ratios

Pass a CSS-valid string or a number.

<AspectRatio ratio="7 / 5">…</AspectRatio>
<AspectRatio ratio={5 / 4}>…</AspectRatio>
<AspectRatio ratio="2.35 / 1">…</AspectRatio>

Under the hood this writes to style.aspectRatio, so anything the CSS aspect-ratio property accepts is valid.

Rounded

Corner-radius presets. When set to anything other than "none", overflow-hidden is added automatically so clipped children match the rounded corners.

ValueTailwind
"none" (default)—
"sm"rounded-sm
"md"rounded-md
"lg"rounded-lg
"xl"rounded-xl
"2xl"rounded-2xl
"3xl"rounded-3xl
"full"rounded-full

Object fit

Single <img> / <video> / <iframe> / <picture> children automatically receive block size-full, and objectFit maps to the corresponding Tailwind object-* class.

ValueTailwind
"cover"object-cover
"contain"object-contain
"fill"object-fill
"none"object-none
"scale-down"object-scale-down

Non-media children are absolutely positioned with inset-0 size-full.

Polymorphic render

Replace the default <div> with a semantic element.

<AspectRatio ratio="video" render={<figure />}>
  <img src="/photo.jpg" alt="" />
</AspectRatio>

Accessibility

  • AspectRatio is a structural primitive — it applies no ARIA roles.
  • Always provide alt text on <img> children — the wrapper does not carry any accessible name.
  • Use render={<figure />} + a <figcaption> sibling when the content benefits from a semantic caption.

API Reference

AspectRatio Props

PropTypeDefaultDescription
ratio"square" | "video" | "portrait" | "landscape" | "ultrawide" | "vertical" | "golden" or string or number"video"Target aspect ratio
rounded"none" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "full""none"Corner radius — auto-applies overflow-hidden when non-none
objectFit"cover" | "contain" | "fill" | "none" | "scale-down"—Applied to single media children as object-*
renderReactElement—Polymorphic target
classNamestring—Extra classes
styleCSSProperties—Custom styles — merged with aspect-ratio

Notes

  • Single-child convention. When you pass exactly one <img> / <video> / <iframe> / <picture> child it receives block size-full. Any other child (including multiple) is wrapped with absolute inset-0 size-full.
  • No hooks. Pure wrapper, safe for SSR.
  • Browser support. CSS aspect-ratio works in all modern browsers (Safari 15+, Chrome 88+, Firefox 89+).

Grid

A CSS-grid layout primitive with static and responsive column counts, gap presets, flow control, and per-cell placement via GridItem. Polymorphic render, RTL, and no hard-coded tokens.

Spacer

A decorative gap-filler. Three axis modes, eight sizes, optional grow-to-fill behaviour, and polymorphic render. Accessibility-hidden by default — screen readers skip it.

On this page

PlaygroundInstallationUsageShowcaseNamed ratiosCustom ratiosRoundedObject fitPolymorphic renderAccessibilityAPI ReferenceAspectRatio PropsNotes