> ## Documentation Index
> Fetch the complete documentation index at: https://dnd-grid.blode.md/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Aspect ratio constraints

<div className="not-prose my-6 rounded-lg border border-zinc-200/70 bg-white/70 shadow-sm dark:border-white/10 dark:bg-white/5">
  <iframe
    title="Aspect ratio constraints preview"
    src="https://dnd-grid.com/examples/aspect-ratio-constraints-example?embed=1"
    className="h-[640px] w-full"
    loading="lazy"
  />
</div>

[View source on GitHub](https://github.com/mblode/dnd-grid/blob/main/apps/web/examples/dnd-grid-aspect-ratio-constraints-example.tsx)

## Installation

<Tabs>
<Tab title="CLI">

```bash
npx shadcn@latest add https://dnd-grid.com/r/aspect-ratio-constraints-example.json
```

</Tab>
<Tab title="Manual">

```bash
npm install @dnd-grid/react
```

```css
@import "@dnd-grid/react/styles.css";
```

```tsx title="components/dnd-grid-aspect-ratio-constraints-example.tsx"
"use client";

import {
  applySizeConstraints,
  aspectRatio,
  type ConstraintContext,
  DndGrid,
  defaultConstraints,
  type Layout,
  useContainerWidth,
} from "@dnd-grid/react";
import * as React from "react";

const COLS = 12;
const ROW_HEIGHT = 50;
const GRID_SPACING = 10;

const ratio16x9 = aspectRatio(16 / 9);
const ratio1x1 = aspectRatio(1);

const baseLayout: Layout = [
  { id: "16:9", x: 0, y: 0, w: 6, h: 3, constraints: [ratio16x9] },
  { id: "1:1", x: 6, y: 0, w: 3, h: 3, constraints: [ratio1x1] },
  { id: "free", x: 9, y: 0, w: 3, h: 2 },
];

const createConstraintContext = (
  layout: Layout,
  containerWidth: number,
): ConstraintContext => ({
  cols: COLS,
  maxRows: Number.POSITIVE_INFINITY,
  containerWidth,
  containerHeight: 0,
  rowHeight: ROW_HEIGHT,
  gap: [GRID_SPACING, GRID_SPACING, GRID_SPACING, GRID_SPACING],
  containerPadding: [GRID_SPACING, GRID_SPACING, GRID_SPACING, GRID_SPACING],
  layout,
});

const applyInitialConstraints = (
  layout: Layout,
  containerWidth: number,
): Layout => {
  const context = createConstraintContext(layout, containerWidth);
  return layout.map((item) => {
    if (!item.constraints?.length) return item;
    const size = applySizeConstraints(
      defaultConstraints,
      item,
      item.w,
      item.h,
      "se",
      context,
    );
    if (size.w === item.w && size.h === item.h) return item;
    return { ...item, ...size };
  });
};

export function AspectRatioConstraintsExample() {
  const { width, containerRef, mounted } = useContainerWidth({
    measureBeforeMount: true,
  });
  const [layout, setLayout] = React.useState<Layout>(baseLayout);
  const [ready, setReady] = React.useState(false);

  React.useEffect(() => {
    if (!mounted || width <= 0 || ready) return;
    setLayout(applyInitialConstraints(baseLayout, width));
    setReady(true);
  }, [mounted, ready, width]);

  return (
    <div ref={containerRef}>
      {mounted && ready && (
        <DndGrid
          layout={layout}
          cols={COLS}
          rowHeight={ROW_HEIGHT}
          width={width}
          gap={GRID_SPACING}
          containerPadding={GRID_SPACING}
          onLayoutChange={setLayout}
        >
          {layout.map((item) => (
            <div key={item.id} className="grid-item">
              {item.id}
            </div>
          ))}
        </DndGrid>
      )}
    </div>
  );
}
```

</Tab>
</Tabs>

## Usage

```tsx
import { AspectRatioConstraintsExample } from "@/components/dnd-grid-aspect-ratio-constraints-example";

export default function Page() {
  return <AspectRatioConstraintsExample />;
}
```