跳到正文
册页

容器

AspectRatio - 宽高比

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

用法

什么时候用它

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

说明

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

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

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

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

结构

AspectRatio anatomy
部件说明
盒子必填一个 relative、占满宽度的 <div>,aspect-ratio 是以内联样式挂上去的。用样式而不用类,是因为 Tailwind 只能生成它在源码里逐字读到的东西,而这个值是运行时才到的。
子元素必填每一个直接子元素,都被抬出文档流、拉满整个盒子。比例守得住靠的就是这一点:里面没有任何东西能贡献高度,所以本身没有固有尺寸的内容照样拿到整个盒子。
裁切直接子级的 <img> 或 <video> 上的 object-cover,所以媒体是填满盒子,而不是在里面留出黑边。不能被裁的内容自己设 object-contain。

实践建议

推荐

  • 凡是图片落地时本来会引起重排的地方,都该用它。那次重排就是 Core Web Vitals 分数在量的布局偏移,而把盒子先占住就是全部的修法。
  • 整幅画面都重要时,要在子元素上设 object-contain——logo、图示、截图。默认是裁切,这对照片是对的,对任何边缘本身有含义的东西都是错的。
  • 要给它一个宽度。它是 w-full,所以放进一个自己没有宽度的容器里,它也就没有高度,而一个有比例、没有尺寸的盒子等于不在。

避免

  • 不要在它旁边退回 padding-top 百分比那套老办法。那个百分比是对着宽度解析的,这既是它能成立的原因,也是它作为 flex 子项就失效、还会把元素自己的内边距吃掉的原因。
  • 不要往里放文字还指望盒子会变高。每个子元素都是绝对定位的,所以比盒子长的段落是被 overflow-hidden 裁掉,而不是把盒子撑开。

示例

reserved boxes

三个在里面还没有任何东西时就知道自己高度的盒子。这里每个子元素都完全没有固有尺寸——它就是一个空 div——而盒子照样撑住了,因为每一个直接子元素都被拿出常规流、拉伸到填满它。这就是全部机制:里面没有任何东西能贡献高度,所以里面也没有任何东西能破坏这个比例。

16 / 9
4 / 3
1 / 1

a grid that cannot reflow

它存在所针对的那个场景:一个封面还没到位的媒体网格。每个盒子已经是对的高度,所以图片落下来时,它们下面的东西一动不动——而那种移动正是 Cumulative Layout Shift 分数在度量的东西。骨架自己没有尺寸;它填满盒子,是因为每一个直接子元素都被拉伸到盒子大小,这意味着加载中状态和加载完状态占据同一个矩形,是构造使然,而不是靠某人手工同步的两个数字。

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

the ratio wins

内容装不下时这个盒子会做什么,而这正是那种没人会去读、直到它咬人为止的取舍。每一个直接子元素都被拿出常规流,容器把溢出藏起来,所以比盒子长的内容会被裁掉,而不是被允许把高度顶开——比例是那个承诺,而这就是承诺被兑现的样子。当那些字必须可读时,给子元素它自己的滚动,就像第二个盒子那样;当它们不必可读时,就去拿一个能长大的盒子,而不是一个不能的。

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,无障碍树上不会多出任何东西。
  • 在内容到达之前先把高度占住,下面的东西才不会在指针或读者点下去的那一刻从底下挪走。