Skip to content

PlAspectRatio

A box that keeps a proportion whatever width it is given. It draws nothing. What it does is reserve the space, so a picture that arrives late does not reflow the page around it.

React
tsx
import { PlAspectRatio } from 'plass-ui';

<PlAspectRatio ratio="16 / 9" rounded>
  <img src="/cover.jpg" alt="" />
</PlAspectRatio>;
dart
import 'package:plass_ui/plass_ui.dart';

PlAspectRatio(
  ratio: 16 / 9,
  rounded: true,
  child: Image(image: cover),
);

Props

PropTypeDefaultDescription
rationumber | string1The proportion to hold, written the way CSS writes it — a number (1.5) or a ratio ('16 / 9')
fit'cover' | 'contain' | 'fill' | 'none''cover'How a single piece of media inside is fitted. Reaches a direct img, video, canvas, svg or iframe only
roundedbooleanfalseRounds the corners to the size step of the house radius ladder
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Which radius step rounded uses — the size of the sheet, never a height or a type scale
renderRenderPropRenders something other than a <div> (<figure />, <a href="…" />)
childrenReactNodeWhat the proportion holds
PropTypeDefaultDescription
childWidget?What the proportion holds
ratiodouble1The proportion, as width over height. Written as the division — 16 / 9 — which is how Flutter states an aspect ratio everywhere else
fitPlAspectFit?nullHow the child is fitted, or null to lay it out normally — Flutter has no "media only" the way a browser does, so a fit applied by default would scale a column of prose
roundedboolfalseRounds the corners to the size step of the house radius ladder
sizesharedPlassSizePlassSize.mdWhich radius step rounded uses — the size of the sheet, never a height or a type scale

Every native <div> attribute passes straight through.

ratio is a double written as the division, 16 / 9, which is how Flutter states an aspect ratio everywhere else, and it asserts rather than clamping: a ratio of zero is a mistake, not a shape.

size is the only shared axis here, and it is the size of the sheet, which radius step rounded uses. There is no variant, no color and no elevation: a layout component that drew a surface would make a proportion a visual decision. What the shared axes mean across the library is in prop conventions.

Examples

ratio

CSS's own aspect-ratio, untranslated, a number or a ratio, both reaching the property as written. A caller who already knows 16 / 9 has nothing to look up.

React

fit

The one convenience on top of the proportion. The four words are object-fit's own: cover fills the box and crops, contain letterboxes, fill stretches, none draws at the content's own size.

cover is the one a thumbnail wants, a thumbnail that letterboxes itself is a thumbnail with two grey bands in it. contain is for the picture whose whole subject matters: a diagram, a logo, a scan.

A single img, video, canvas, svg or picture that is a direct child is stretched to the full box and then fitted, which is the pair of declarations every use of this component would otherwise start with. Anything else is laid out normally and fit does not reach it. An iframe takes the sizing but not the fit: an embed lays its own content out, and object-fit has nothing to act on.

It is null by default here, where React defaults it to cover. In a browser object-fit is a property only a replaced element answers, so React can default it and have it quietly not reach a <div> full of text. Flutter has no such distinction. A fit is a FittedBox around whatever the child happens to be, and one applied by default would scale a column of prose. So it is opt-in, and it applies to everything.

An Image that already carries its own BoxFit needs nothing here.

React

rounded

Off by default. A photograph with its corners cut is a decision about the photograph, not about the box holding it, but it is such a common one that making the caller reach for a classNamea ClipRRect would be perverse, so it is a boolean and size picks the step.

The box clips whatever it holds either way. Without that, a cover image would spill straight out of the proportion it was just given and the component would only be reserving space rather than holding anything to it.

React

Accessibility

  • The box adds no role and no semantics node of its own. It is a measurement, and a measurement is not something a screen reader should have to announce.
  • Nothing here supplies a description of the picture inside. That picture is the caller's, and so is what it means.
  • render is how the box becomes the element the content actually calls for, a <figure> around a picture with a caption, an <a> around a card's cover.

Differences from the React build

ReactFlutterWhy
fit defaults to 'cover'fit defaults to nullobject-fit reaches only a replaced element, so React can default it harmlessly. A FittedBox reaches whatever it is given, and one applied by default would scale a column of text.
ratio takes '16 / 9'ratio takes 16 / 9A double written as the division, which is how Flutter states an aspect ratio everywhere else. There is no string form to parse.
renderThere is no element to swap. A widget that has to be a link or a figure is wrapped in one.
childrenchildFlutter's name.
className, styleThere is no class list and no style attribute to pass through.

Released under the MIT License