Skip to content

explainers-by-googlers/css-fit-text

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

CSS fit-width text Explainer

This proposal is an early design sketch by Blink Layout Team in Google to describe the problem below and solicit feedback on the proposed solution. It has not been approved to ship in Chrome.

Participate

Table of Contents

Introduction

In text layout, web authors want to align the lines with both ends of the container, but web authors want to achieve this by adjusting the font size instead of justification. Currently, there is no such method in CSS, and the only option is to manually adjust the font size through trial and error or using JavaScript.

Web authors want to fit the text into a container of a specific size without it overflowing. For example, if the container width is narrow and a long word inevitably overflows the container, web authors want to reduce the font size to make it fit within the container. Web authors want to avoid text overflowing the container due to unexpectedly long words used in text translations or when end-users provide arbitrary text.

Why CSS?

A CSS solution elevates "fit-width text" from a complex, potentially janky scripting problem to a fundamental, performant, and easy-to-use aspect of the CSS layout system.

Performance

JavaScript solutions for fitting text typically involve reading element dimensions (layout reads), calculating new styles (computation), and writing new styles (layout writes). When triggered frequently (e.g., during window resizing, container resizing via ResizeObserver, or dynamic content loading), this read-compute-write cycle can lead to layout thrashing, causing jank, slow rendering, and high CPU usage. A native CSS implementation can integrate the text fitting calculation directly into the browser's existing layout and rendering pipeline. This means the fitting happens efficiently as part of the initial layout or subsequent reflows, without the overhead and potential timing issues of stepping in and out of JavaScript.

Improved User Experience

JavaScript-based fitting often suffers from a "flash of unstyled content" or a visible "jump" or reflow as the text is initially rendered at one size and then resized by the script. By making text fitting a native layout property, the browser can calculate the final size/scale before or during the initial paint, resulting in text that appears correctly sized and positioned from the start, providing a much smoother and more professional user experience. This will also improve the quality of the FCP.

Simplified Authoring & Maintainability

Achieving robust text fitting in JavaScript is complex. It requires handling initial load, window resizes, container resizes, potential font loading issues, minimum/maximum size constraints, different fitting methods (font size vs. scaling), and managing the state across various elements. A declarative CSS solution allows developers to achieve the desired behavior with a simple property declaration, significantly reducing the amount of code they need to write, test, and maintain. It integrates seamlessly into the CSS cascade, can be easily controlled by media queries or container queries, and reduces the reliance on complex imperative logic.

Goals

  • Provides a way to align both ends of the text with the width of the container. Consider both cases: fitting by enlarging the text and fitting by shrinking the text.

Non-goals

  • Provide a way to adjust the container width to match to the widest line.
  • Provide a way to adjust font size to fit text to the container's width and height.
  • Introduce a new line-wrapping algorithm to fit lines to the container width.

Use cases

Publishing (news sites, blogs, magazines, portfolios) heavily relies on flexible and visually appealing typography that adapts to various layouts and screen sizes. This feature is highly relevant here, particularly for fluid & responsive headlines. This includes:

Expanding

A short headline for a prominent article might look lost in a wide column on a desktop, text-grow could automatically increase its size or character/word spacing to fill the available width, creating a stronger visual impact without manual tweaking or JS calculations based on breakpoints.

  • Original:
    <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et ...
    o
  • A) Enlarge each line to fit them to the container width:
  • B) Enlarge all lines to fit the widest line to the container width:

Shrinking

A long headline containing several words or a very long word might easily overflow its container on smaller screens or in constrained sidebar layouts. Text-shrink ensures the headline reduces its size or adjusts spacing to fit within the allocated width, preventing truncation or awkward line breaks without needing JS to measure and resize.

  • Original:
    <div>Effective CSS architecture emphasizes componentization for easier ...
  • A) Making an overflowing line smaller to fit it to the container width:
  • B) Making all lines smaller to fit the overflowing line to the container width:

Fitting Captions and Pull Quotes

Text accompanying images or used as pull quotes often needs to precisely fit the width of the related content block. 'Shrinking' can prevent overflow, while 'Expanding' can be used to ensure short captions don't look awkward in wide containers.

Aligning Text Blocks

For certain stylistic layouts, ensuring paragraphs or short text blocks align perfectly to the container's left and right edges by subtly adjusting spacing or size can be achieved declaratively with these properties, rather than relying on justified text which can sometimes lead to excessive gaps.

[Potential Solution]

We'd like to introduce a new CSS property.

  • Name: 'text-fit'
  • Value: <fit-type> <fit-target>? <scale-limit>?
  • Initial: none
  • Applies to: text containers
<fit-type> = none | grow | shrink
  • grow: Allow lines to fit the target container width by enlarging text.
  • shrink: Allow lines to fit the target container width by shrinking text.
<fit-target> = consistent | per-line | per-line-all
  • consistent: Makes all lines in the target container larger/smaller by a scaling factor for the widest line.
  • per-line: Makes each line in the target container larger/smaller independently, except for the last line.
  • per-line-all: Make each line in the target container larger/smaller independently, including the last line.
<scale-limit> = <percentage>

The maximum scaling factor for grow, or the minimum scaling factor for shrink.

See w3c/csswg-drafts#12887.

Examples

Expanding

text-fit: grow per-line-all;

See Use cases Expanding A. If a line width is narrower than the container width, line's font-size is increased so that the line width matches the container width. Even if a single font-size is used in the container, each line might have different font-sizes. If a line width is wider than the container width, the line is unchanged.

text-fit: grow per-line-all 200%;

Ditto. However the text will expand up to twice the original size. So, lines might be narrower than the container width.

text-fit: grow consistent;

See Use cases Expanding B. Compute a scaling factor so that the widest line in the container fits to the container width, and scale all lines in the container by the scaling factor. If the widest line is wider than the container width, nothing happens.

Shrinking

text-fit: shrink per-line-all;

See Use cases Shrinking A. If a line width is wider than the container width, line's font-size is decreased so that the line width matches the container width. Even if a single font-size is used in the container, each line might have different font-sizes. If a line width is narrower than the container width, the line is unchanged.

text-fit: shrink per-line-all 50%;

Ditto. However the text will shrink down to half the original size. So lines might be wider than the container width.

text-fit: shrink consistent;

See Use cases Shrinking B. Compute a scaling factor so that the widest line in the container fits to the container width, and scale all lines in the container by the scaling factor. If the widest line is narrower than the container width, nothing happens.

Detailed design discussion

  • Items contained in a line box are classified as either "scalable" or "static", and only "scalable" items are affected by this feature.
    • See w3c/csswg-drafts#12888.
    • All texts are scalable even if a text has a font-size diffrent from the container font-size.
    • %-based letter-spacing and word-spacing are scalable.
    • Replaced elements such as <img> and <input> are static.
    • Atomic inlines are static
    • padding, border, and margin for inline direction are static.
    • This classification may be configurable in the future.
  • How does this interact with properties with <length>.
    • Should the <length> be scaled or not? See w3c/csswg-drafts#12888.
    • In general, <length> values are not scaled. 4px should be 4px even if a line is scaled. Font-relative length units such as em are not scalable too. Exceptionally, the percentage values ​​of some CSS properties should be linked to the rendered font size, so they are scalable.
  • Accessibility: See w3c/csswg-drafts#12886.
  • Text decoration, emphasis marks, ruby annotations should work well with scaled font-size.
  • This feature should not affect the container's intrinsic size.

Considered alternatives

  • Implement this behavior as a value of font-size property, like font-size:fit-width. It's technically difficult because the container width might depend on the font-size.

References & acknowledgements

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors