Aspect Ratio

Displays content within a desired ratio. Useful for maintaining consistent proportions for images, videos, and embeds.

Docs
Image
import { AspectRatio } from "~/components/aspect-ratio";

export default function AspectRatioBasicDemo() {
  return (
    <div class="w-full max-w-sm overflow-hidden rounded-md">
      <AspectRatio ratio={16 / 9}>
        <img
          src="https://images.unsplash.com/photo-1588345921523-c2dcdb7f1dcd?w=800&auto=format&fit=crop&q=60"
          alt="Image"
          class="size-full rounded-md object-cover"
        />
      </AspectRatio>
    </div>
  );
}

Installation

CLI

Run the following command to add the component to your project:

npx @ark-preset/cli@latest add aspect-ratio

Manual

Create the recipe file at src/components/recipes/aspect-ratio.ts:

import { tv, type VariantProps } from "tailwind-variants";

export const aspectRatioVariants = tv({
  base: "relative w-full",
});

export type AspectRatioVariants = VariantProps<typeof aspectRatioVariants>;

Create the component file at src/components/aspect-ratio/index.tsx:

import { splitProps, type Component, children } from "solid-js";
import { aspectRatioVariants } from "../recipes/aspect-ratio";
import { ark, type HTMLArkProps } from "@ark-ui/solid/factory";

type AspectRatioProps = HTMLArkProps<"div"> & {
  ratio?: number;
};

const AspectRatio: Component<AspectRatioProps> = (props) => {
  const [local, others] = splitProps(props, ["class", "ratio", "children"]);
  const resolvedChildren = children(() => local.children);

  return (
    <ark.div
      class={aspectRatioVariants({ class: local.class })}
      style={{ "padding-bottom": `${100 / (local.ratio ?? 16 / 9)}%` }}
      {...others}
    >
      <ark.div class="absolute inset-0" style={{ position: "absolute", inset: 0 }}>
        {resolvedChildren()}
      </ark.div>
    </ark.div>
  );
};

export { AspectRatio, aspectRatioVariants };

Note: Make sure your project has the Tailwind CSS theme variables set up (--background, --foreground, --ring, --border, etc.) or override the utility classes to match your design system.

Usage

Basic Usage

Image
import { AspectRatio } from "~/components/aspect-ratio";

export default function AspectRatioBasicDemo() {
  return (
    <div class="w-full max-w-sm overflow-hidden rounded-md">
      <AspectRatio ratio={16 / 9}>
        <img
          src="https://images.unsplash.com/photo-1588345921523-c2dcdb7f1dcd?w=800&auto=format&fit=crop&q=60"
          alt="Image"
          class="size-full rounded-md object-cover"
        />
      </AspectRatio>
    </div>
  );
}

Square

Use a 1:1 aspect ratio to display square content.

Square Content
import { AspectRatio } from "~/components/aspect-ratio";

export default function AspectRatioSquareDemo() {
  return (
    <div class="w-full max-w-sm">
      <AspectRatio ratio={1 / 1}>
        <div class="flex size-full items-center justify-center rounded-md bg-muted text-sm text-muted-foreground">
          Square Content
        </div>
      </AspectRatio>
    </div>
  );
}

API Reference

PropTypeDefaultDescription
rationumber16/9The desired aspect ratio
classstringAdditional CSS classes