IX Surfaces

Star on GitHubFeedback
IX SurfacesNative HTMLot-ratio

Aspect ratio

A frame kept to a ratio and marked the way a printer marks a crop: short lines outside each corner, never a border.

Report an issue with Aspect ratio

Example

16 by 9
16 by 9
16 by 9
crop, 16 : 9
16 by 9
crop, 4 : 5
4 by 5
diagonal, 16 : 9
16 by 9
diagonal, 4 : 5
4 by 5
square, 16 : 9
16 by 9
square, 4 : 5
4 by 5

Install

Run it in a project that has the shadcn CLI set up. It brings the 0nlyType base along.

npx shadcn@latest add https://thedirectors.agency/ui/r/aspect-ratio.json

Usage

This example also uses Toggle group.

npx shadcn@latest add https://thedirectors.agency/ui/r/toggle-group.json
aspect-ratio-example.tsx
"use client"import * as React from "react"import { AspectRatio } from "@/components/ui/aspect-ratio"import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"const ratios = [["16:9", 16 / 9],["4:3", 4 / 3],["1:1", 1],["4:5", 4 / 5],] as constexport default function Example() {const [ratio, setRatio] = React.useState("16:9")const value = ratios.find(([name]) => name === ratio)?.[1] ?? 16 / 9return (<div className="grid gap-10">{/* Radix single groups clear on a second press; a ratio is always one of the four. */}<ToggleGroup type="single" value={ratio} onValueChange={(v) => v && setRatio(v)} aria-label="Ratio">{ratios.map(([name]) => (<ToggleGroupItem key={name} value={name}>{name}</ToggleGroupItem>))}</ToggleGroup>{/* One ratio, three frames: the crop, the diagonal and the square all follow the choice. */}<div className="grid items-start gap-x-16 gap-y-14 sm:grid-cols-3"><AspectRatio ratio={value} label /><AspectRatio ratio={value} label variant="diagonal" /><AspectRatio ratio={value} label variant="square" /></div></div>)}

Contract

  • Underneath: native aspect-ratio.
  • Anatomy: <div class="ot-ratio" data-variant="crop | diagonal | square" data-orient="landscape | portrait | square" style="--ratio: 1.7778">, with a ot-fraction naming it (aria-hidden; a .ot-sr says "16 by 9"), and for the square .ot-ratio-rest holding the remainder's fraction. --ratio is a registered number, so it eases; registered, it doesn't inherit, so --r carries it to the parts and pseudo-elements. The fraction keeps to the frame (min(--ot-f, 17cqi)).
  • A frame kept to a ratio and marked like a printer's crop: short lines outside each corner and nothing between them, no border. Change --ratio and the frame eases to it while the fraction rolls.
  • Diagonal: the paste-up artist's scaling line, a hairline from the foot of the start edge to the head of the end edge. Any frame whose corner lies on it has the same ratio, which is how a picture was scaled before software. The ratio is written along the line, standing on it (rotate(-atan2(1, --r))), so as the frame eases the line and the words swing together. Mirrored in right-to-left.
  • Square: the largest square is ruled off from the start edge, or from the head when the frame stands tall, the way a book designer finds the square in a page and the rectangle it leaves. The ratio sits in the square; what's left is named by its own ratio in the pencil (16 : 9 leaves 7 : 9, 4 : 5 leaves 4 : 1). The rule is a background placed at 100% / --r, so it glides as the frame eases, and its length is clamped to nothing at 1 : 1, where there is nothing left. The remainder's name fades back in once the rule has arrived.
  • Forced colours keep the marks and lines (they are background images) in CanvasText.

Props

Props of Aspect ratio
PropTypeDefaultWhat it does
variant"crop" | "diagonal" | "square""crop"crop: only the printer's trim marks outside the corners. diagonal: the paste-up artist's scaling line, from the foot of the start edge to the head of the end edge, with the ratio written along it, standing on it; every frame whose corner lies on that line has the same ratio, and as the ratio changes the line and the words swing together. square: the largest square is ruled off from the start, or from the head when the frame stands tall, and what's left is named by its own ratio in the pencil (16 : 9 leaves 7 : 9); the rule glides as the ratio eases, and at 1 : 1 there is nothing left.
rationumber16 / 9Width over height. Change it and the frame eases to the new ratio.
labeltrue | ReactNodetrue sets the ratio in the middle as a fraction, which rolls when the ratio changes. Any other node is shown as given.

Craft

Where its move comes from

Where its move comes from
ComponentReferenceMove
Resizable, aspect ratioPaul Rand dimension linesShares measured; a printer's crop marks
Diagonal aspect ratioThe paste-up artist's scaling diagonalThe ratio written along the line that keeps it
Square aspect ratioThe book designer's square in the pageThe square ruled off, the rest named by its own ratio

How it moves

How it moves
ComponentArticulationWhat moves
Aspect ratioBreathThe frame eases to the ratio; the fraction rolls
Diagonal aspect ratioSwingThe line and the ratio written on it swing to the new diagonal with the frame
Square aspect ratioGlideThe square's rule glides to its new place; the remainder's name comes back once it lands