AspectRatio

A layout primitive that constrains its content to a fixed width-to-height ratio.

Overview

An AspectRatio reserves a box at a fixed width-to-height ratio using the native CSS aspect-ratio property — the classic use is holding responsive media (an image, a video, a map embed) so the layout doesn’t reflow while the asset loads. It fills the available width and derives its height from the ratio.

Anatomy

A single <div> set to width: 100%, the given aspect-ratio, and overflow: hidden. Size a single child to width: 100%; height: 100% (e.g. an <img> with object-fit: cover) to fill the box. There is no sketch layer — this primitive is purely structural.

Variants & States

AspectRatio is a static layout box — it has no interactive states. The only variation is the ratio value itself.

State Status Notes
Hover Not implemented Not interactive.
Focus Not implemented Not focusable.
Disabled Not implemented
Loading Not implemented
Error Not implemented

Usage

Do

  • Place a single child sized to width: 100%; height: 100% (an <img> with object-fit: cover is the common case).
  • Pass the ratio as a number expression like 16 / 9 or 4 / 3 so intent stays readable.
  • Constrain the outer width (e.g. a max-width wrapper) — the box derives its height from that width.

Don't

  • Don't set an explicit height on the box — the ratio derives it from the width.
  • Don't use it purely to add spacing; it's for reserving media proportions, not general layout gaps.

Accessibility

Content

N/A — AspectRatio has no fixed content model. Content is whatever single element you place inside, sized to fill the box.

Props API

React@ghds/react

PropTypeDefaultDescription
rationumber1Desired width-to-height ratio, e.g. 16 / 9 for widescreen or 1 for a square.
...restHTMLAttributes<HTMLDivElement>Native <div> attributes (className, style, etc.) pass through.

Web Components@ghds/web-components

PropTypeDefaultDescription
rationumber1Reflected attribute; sets the host aspect-ratio. Slot a single child to fill the box.

React Native@ghds/react-native

PropTypeDefaultDescription
rationumber1Width-to-height ratio applied via the native aspectRatio style.
childrenReactNodeContent constrained to the ratio box.
styleStyleProp<ViewStyle>Extra style merged onto the ratio box.
accessibilityLabelstringAccessible label for the region.
testIDstringTest handle for queries.

Code examples

// React — @ghds/react
import { AspectRatio } from '@ghds/react/aspect-ratio';

<AspectRatio ratio={16 / 9}>
  <img src="https://example.com/cover.jpg" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
</AspectRatio>;
<!-- Web Components — @ghds/web-components -->
<script type="module">
  import '@ghds/web-components/aspect-ratio';
</script>
<gh-aspect-ratio ratio="1.7778">
  <img src="https://example.com/cover.jpg" style="width: 100%; height: 100%; object-fit: cover;" />
</gh-aspect-ratio>
// React Native — @ghds/react-native
import { AspectRatio } from '@ghds/react-native/aspect-ratio';
import { Image } from 'react-native';

<AspectRatio ratio={16 / 9}>
  <Image
    source={{ uri: 'https://example.com/cover.jpg' }}
    style={{ width: '100%', height: '100%' }}
    resizeMode="cover"
  />
</AspectRatio>;

Live Demo

React and Web Components render live below, driven by the same tokens — toggle dark mode in the header to see both respond identically. React Native can’t run in a browser without additional react-native-web wiring (not set up in this site), so its usage is shown as a code sample instead.

React @ghds/react

Web Components @ghds/web-components

16 / 9
1 / 1
4 / 3