跳到正文
misoto22 design

容器

AspectRatio 宽高比

一个盒子,不管里面装什么都保持形状。

用法

什么时候用它

高度必须在内容加载之前就知道——否则每来一张图就要重排一次的媒体网格。
TSX
import { AspectRatio } from '@misoto22/design'

说明

一个盒子,不管里面装什么都保持形状。

这是唯一一个真正难以手搓的布局原语。大家伸手就去用的 padding-top: 56.25%宽度的百分比——它能成立是因为这个,它在盒子成为 flex 或 grid 子项的那一刻悄悄失效也是因为这个,而且它还会把元素自己的 padding 一起卷进去。现代的 aspect-ratio 属性一行就干完同一件事,前提是里面没有任何东西撑出高度——底下那套绝对定位保证的正是这一点。

于是:盒子声明比例,每一个直接子元素都被拉满并脱离文档流。这意味着一个本身完全没有固有尺寸的子元素——一个空的 <div>、一张要量容器才知道自己多大的地图、一块骨架屏——照样拿到整个盒子;而 <img><video> 是裁切填满,不是留黑边。不能被裁的内容,请自己加 object-contain

当高度必须在内容加载之前就知道时,用它:最常见的情形是一个媒体网格,否则每来一张图它就重排一次——而那次重排,正是 Core Web Vitals 分数在量的那个布局偏移。

结构

AspectRatio anatomy
部件说明
Box必填A relative, full-width <div> carrying aspect-ratio as an inline style. A style and not a class because Tailwind can only generate what it reads verbatim in the source, and this value arrives at runtime.
Children必填Every DIRECT child, taken out of flow and stretched to fill the box. That is what guarantees the ratio holds: nothing inside can contribute a height, so content with no intrinsic size of its own still gets the whole box.
Cropobject-cover on a direct <img> or <video>, so media fills the box rather than being letterboxed inside it. Content that must not be cropped sets object-contain on itself.

实践建议

推荐

  • Reach for it wherever a reflow would otherwise happen when an image lands. That reflow is the layout shift a Core Web Vitals score measures, and reserving the box is the whole fix.
  • Set object-contain on the child when the whole picture matters — a logo, a diagram, a screenshot. The default crops, which is right for a photograph and wrong for anything with an edge that means something.
  • Give it a width. It is w-full, so inside a container with no width of its own it has no height either, and a box with a ratio and no size is a box that is not there.

避免

  • Do not fall back to the padding-top percentage trick beside it. That percentage resolves against the WIDTH, which is why it works at all and also why it breaks as a flex child and eats the element’s own padding.
  • Do not put text in it and expect the box to grow. Every child is absolutely positioned, so a paragraph longer than the box is clipped by overflow-hidden rather than pushing it open.

示例

reserved boxes

Three boxes that know their height before anything is inside them. Each child here has no intrinsic size at all — it is an empty div — and the box holds open anyway, because every direct child is taken out of flow and stretched to fill it. That is the whole mechanism: nothing inside can contribute a height, so nothing inside can break the ratio.

16 / 9
4 / 3
1 / 1

a grid that cannot reflow

The case this exists for: a media grid whose covers have not arrived. Each box is already the right height, so when the images land nothing under them moves — and that movement is exactly what a Cumulative Layout Shift score is measuring. The skeleton has no size of its own; it fills the box because every direct child is stretched to it, which means the loading state and the loaded state occupy the same rectangle by construction rather than by two numbers someone kept in step.

Why the system spends no colour
Three densities, one component
Five diagram shapes software needs

the ratio wins

What the box does when the content does not fit, which is the trade nobody reads about until it bites. Every direct child is taken out of flow and the wrapper hides its overflow, so content longer than the box is CLIPPED rather than allowed to push the height — the ratio was the promise, and it is the promise kept. Where the words have to be readable, give the child its own scroll, as the second box does; where they do not, reach for a box that can grow instead of one that cannot.

Adds the five diagram renderers, the canvas chrome around them, and a share-card export at 1200 by 630. The specification types mirror archify, so a document authored for that tool renders here with no translation step.

clipped

Adds the five diagram renderers, the canvas chrome around them, and a share-card export at 1200 by 630. The specification types mirror archify, so a document authored for that tool renders here with no translation step.

overflow-y-auto on the child

无障碍

  • 一个没有 role 的普通盒子:它只约束几何,什么都不说,所以里面的 <img> 留着自己的 alt,无障碍树上不会多出任何东西。
  • 在内容到达之前先把高度占住,下面的东西才不会在指针或读者点下去的那一刻从底下挪走。