← CSS Animation · 能力速览 / Fit-to-Width:纯 CSS 让文本撑满宽度 待审核 11 / 22
综合应用 · view(inline) + scroll-snap

Fit-to-Width:纯 CSS 让文本撑满宽度

本页建立在 View Timelineanimation-timeline: view() 之上。不用 JS 测量、不硬编码任何 font-size,让一行文本自动缩放到正好填满容器宽度。手法出自 Roman Komarov · Fit-to-Width Text:把本为滚动联动设计的 Scroll-Driven Animations 反用成「在样式层读取尺寸比例」的工具——view(inline) 时间线在 entry-crossing 区间的进度,恰好等于容器宽度 ÷ 文本固有宽度,拿它驱动 scale() 即可。整页零脚本:下面的宽度调节用 resize、文本编辑用 contenteditable,缩放全靠 CSS。

本页效果依赖 animation-timeline: view(inline)(Scroll-Driven Animations,需 Chromium 115+)。不支持的浏览器会自动回退为普通 text-overflow: ellipsis,请用 Chrome / Edge 打开以查看真实效果。

1 · 拖右下角改宽度、直接改文字

只缩小、不放大:文本天生比容器宽时被缩放贴合;若文本本就窄于容器,则维持原始字号(scale 封顶 1)。所以容器拉得越窄,字越小,且右边缘始终贴着容器

2 · 不同长度的多行、同一宽度

每行都是一个独立的 view(inline) subject,各算各的比例,因此字数越少的行字号越大,但所有行的实际渲染宽度一致——这是该手法最直观的展示。

3 · 原理

三个零件合起来,把「尺寸比」算进了样式:

  • 其一 overflow: hidden 让容器成为 scroll container(有 scrollport,只是不显示滚动条)。
  • 其二 文本 inline-size: max-content 取固有宽度,通常比容器更宽,于是溢出。
  • 其三 scroll-snap-type: both mandatoryscroll-snap-align: start,把滚动偏移钉死在起点

在这个被钉住的滚动位置上,view(inline) 时间线于 entry-crossing 区间的进度值 = 容器宽度 ÷ 文本固有宽度

@keyframes 里只写了 from(进度 0 时 scale(0)),to 隐式为元素原状态 scale(1)。于是被钉住位置的进度 p 就把字号缩放成 scale(p),正好等于那个比例。margin-block-end: -1lh 抵消缩放后行盒残留的高度,让垂直节奏不塌;transform-origin: 0 0 保证从左上角缩放、左边缘不漂移。

4 · 核心 CSS

.fit-box {                        /* 容器 = 隐式 scroll container,滚动钉在起点 */
  overflow: hidden;
  scroll-snap-type: both mandatory;
  font-size: 7rem;                /* 够大 → 必定溢出 → 必定缩放 */
}

.fit-box > .line {
  inline-size: max-content;       /* 文本固有宽度 */
  transform-origin: 0 0;
  animation: fit-ratio linear;
  animation-timeline: view(inline);
  animation-range: entry-crossing;  /* 进度 = 容器/文本 比例 */
  scroll-snap-align: start;
  contain: layout;
}

@keyframes fit-ratio {
  from { transform: scale(0); margin-block-end: -1lh; }
}

底层机制见本系列 View Timeline