本文へ移動
uiify

Aspect Ratio

A media frame that preserves its width-to-height ratio.

ブラウザー
Chrome 123+Firefox 121+Safari 17.5+
ティア
0
圧縮後のサイズ
268 B
強制レイアウトの上限
0 ms
axe の上限
0
SSR 対応
はい
公開された契約
テストハーネス

プレイグラウンド

16:9 · Cover

An amber sun above overlapping blue mountain ridges
import { AspectRatio } from "@gunkin/uiify";

export default function Example() {
  return (
    <AspectRatio ratio={16 / 9} className="">
      <img src="/mountains.svg" width="640" height="400" alt="An amber sun above blue mountain ridges" />
    </AspectRatio>
  );
}
@layer components {
  [data-uiify-aspect-ratio] {
    border-radius: var(--radius-md);
    background: var(--muted);
  }

  [data-uiify-aspect-ratio] > [data-part="content"] {
    border-radius: inherit;
  }

  [data-uiify-aspect-ratio] > [data-part="content"] > img {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    border-radius: inherit;
    object-fit: cover;
  }
}
import { AspectRatio } from "@gunkin/uiify";

export default function Example() {
  return (
    <AspectRatio
      ratio={16 / 9}
      className="
        rounded-md bg-muted [&>[data-part=content]]:[border-radius:inherit] [&>[data-part=content]>img]:block
        [&>[data-part=content]>img]:[inline-size:100%] [&>[data-part=content]>img]:[block-size:100%]
        [&>[data-part=content]>img]:[border-radius:inherit] [&>[data-part=content]>img]:object-cover
      "
    >
      <img src="/mountains.svg" width="640" height="400" alt="An amber sun above blue mountain ridges" />
    </AspectRatio>
  );
}
/* app.css */

@layer reset, ui, app, tokens, base, demo, components, utilities, theme;

@import "@gunkin/uiify/styles/reset";

@import "@gunkin/uiify/components/behavior.css";

@import "@gunkin/uiify/styles/tokens";

@import "@gunkin/uiify/styles/tailwind";

@import "tailwindcss/utilities.css";

@theme { --spacing: 0.25rem; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }

@source inline('rounded-md bg-muted [&>[data-part=content]]:[border-radius:inherit] [&>[data-part=content]>img]:block [&>[data-part=content]>img]:[inline-size:100%] [&>[data-part=content]>img]:[block-size:100%] [&>[data-part=content]>img]:[border-radius:inherit] [&>[data-part=content]>img]:object-cover');

@layer base { :root { --uiify-control-text: var(--text-sm); } @media (pointer: coarse) { :root { --uiify-control-text: var(--text-base); } } }

/* Authored animation and registered properties used by the Tailwind skin.
 * Visual rules belong in utility recipes; only at-rule definitions live here. */
@layer components {
  @keyframes uiify-presence-in {
    from {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}

@layer components {
  @keyframes uiify-presence-out {
    to {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}

@property --uiify-spinner-tail {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

@property --uiify-spinner-length {
  syntax: "<angle>";
  inherits: false;
  initial-value: 36deg;
}

@layer components {
  @keyframes uiify-spinner-rotate {
    to {
      transform: rotate(360deg);
    }
  }
}

@layer components {
  @keyframes uiify-spinner-orbit {
    0% {
      --uiify-spinner-tail: 0deg;
      --uiify-spinner-length: 36deg;
    }

    50% {
      --uiify-spinner-tail: 90deg;
      --uiify-spinner-length: 324deg;
    }

    100% {
      --uiify-spinner-tail: 360deg;
      --uiify-spinner-length: 36deg;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-pulse {
    50% {
      opacity: 0.45;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-shimmer {
    to {
      background-position: -200% 0;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-reveal {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
}

@property --candle-body-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-body-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-slot {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 100%;
}

@property --candle-wick-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-wick-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-x {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@property --line-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --line-prev-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --line-count {
  syntax: "<integer>";
  inherits: false;
  initial-value: 1;
}

@property --line-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@layer components {
  @keyframes uiify-otp-input-caret-blink {
    50% {
      opacity: 0;
    }
  }
}

使用例

Square

The default ratio is 1. A square frame crops a landscape image at the sides.

An amber sun above overlapping blue mountain ridges
import { AspectRatio } from "@gunkin/uiify";

<AspectRatio>
  <img src="/mountains.svg" width="640" height="400" alt="An amber sun above blue mountain ridges" />
</AspectRatio>

Portrait

Set ratio to 4 / 5 for a portrait frame. The image keeps its proportions while filling the frame.

An amber sun above overlapping blue mountain ridges
import { AspectRatio } from "@gunkin/uiify";

<AspectRatio ratio={4 / 5}>
  <img src="/mountains.svg" width="640" height="400" alt="An amber sun above blue mountain ridges" />
</AspectRatio>

Contain

Apply .uncropped { object-fit: contain; } to keep the whole image visible. The optional skin supplies the frame background.

An amber sun above overlapping blue mountain ridges
import { AspectRatio } from "@gunkin/uiify";

<AspectRatio ratio={16 / 9}>
  <img className="uncropped" src="/mountains.svg" width="640" height="400" alt="An amber sun above blue mountain ridges" />
</AspectRatio>

API

AspectRatio

Prop型既定値説明
rationumber1Positive finite width divided by height. Invalid numbers fall back to 1. When omitted, the CSS custom property can set the ratio.
childrenReactNode—Content placed inside the frame. Intrinsic content cannot enlarge the frame.
classNamestring—Class applied to the frame root.
styleCSSProperties—Native root styles, including --uiify-aspect-ratio when ratio is omitted.
refRef<HTMLElement>—Ref forwarded to the rendered root element.
asElementType"div"Native element or component used for the root.
renderReactElement | ((props, state) => ReactElement)—Replace the rendered root while preserving its props, ref and identity marker.

キーボード

キー操作

アクセシビリティ

Static layout adds no role, focus target or keyboard behavior. Give meaningful images alt text; keep captions outside the frame. Required behavior CSS preserves the ratio even when children have intrinsic dimensions. Optional styles fill images with object-fit: cover; use contain to show the entire image.

スタイリングのフック

data-uiify-aspect-ratiodata-part="content"--uiify-aspect-ratio