<pre class='metadata'>
Title: CSS Text Module Level 5
Shortname: css-text
Level: 4
Status: ED
Work Status: Exploring
Group: csswg
ED: https://drafts.csswg.org/css-text-4/
TR: https://www.w3.org/TR/css-text-4/
Previous Version: https://www.w3.org/TR/2024/WD-css-text-4-20240529/
Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400
Editor: Koji Ishii, Invited Expert, kojiishi@gluesoft.co.jp, w3cid 45369
Editor: Alan Stearns, Adobe Systems, stearns@adobe.com, w3cid 46659
Editor: Florian Rivoal, Invited Expert, https://florian.rivoal.net, w3cid 43241
Abstract: This CSS module defines properties for text manipulation and specifies their processing model. It covers line breaking, justification and alignment, white space handling, and text transformation.
Ignored Vars: letter-spacing
WPT Path Prefix: /css/css-text/
</pre>

<h2 id="intro">
Introduction</h2>

	This module describes the typesetting controls of CSS;
	that is, the features of CSS that control the translation of
	source text to formatted, line-wrapped text.

	This specification describes features introduced in Level 5;
	it is a diff against [[css-text-4]].

<h3 id="text-fit-property">
Text fitting: the 'text-fit' property</h3>

	<wpt title="
		This section has no coverage yet.
	"></wpt>

	<pre class="propdef">
	Name: text-fit
	Value: [ none | grow | shrink ] [consistent | per-line | per-line-all]? <<percentage>>?
	Initial: none
	Applies to: <a>block containers</a>
	Inherited: yes
	Percentages: N/A
	Computed value: specified keywords or computed <<percentage>> value
	Canonical order: per grammar
	Animation type: discrete
	</pre>

	<p>The 'text-fit' property describes how [=inline-level=] contents are
	scaled if they do not fit to the [=line box=].

	<p>Values have the following meanings:

	<dl dfn-for=text-fit dfn-type=value>
		<dt><dfn>none</dfn>
		<dd>
		    The user agent doesn't scale [=inline-level=] contents to fit to
			the [=line box=].
		</dd>

		<dt><dfn>grow</dfn>
		<dd>
		    The user agent scales up [=inline-level=] contents to fit to the
			[=line box=].
		</dd>

		<dt><dfn>shrink</dfn>
		<dd>
		    The user agent scales down [=inline-level=] contents to fit to the
			[=line box=].
		</dd>

		<dt><dfn>consistent</dfn>
		<dd>
		    Specifies that all lines in the container are scaled with a single
			scaling factor.
			This keyword has no effect if ''text-fit/none'' is specified.
			If none of ''text-fit/consistent'', ''text-fit/per-line'', or
			''text-fit/per-line-all'' are specified, ''text-fit/consistent'' is
			assumed.
		</dd>

		<dt><dfn>per-line</dfn>
		<dd>
		    Specifies that each line is scaled with its own scaling factor.
			However, the last line of the block and lines that end in a forced
			break are not scaled.
			This keyword has no effect if ''text-fit/none'' is specified.
		</dd>

		<dt><dfn>per-line-all</dfn>
		<dd>
		    Specifies that each line is scaled with its own scaling factor,
			including the last line of the block and lines that end in a forced
			break.
			This keyword has no effect if ''text-fit/none'' is specified.
		</dd>

		<dt><dfn>&lt;percentage&gt;</dfn>
		<dd>
		    Specifies the limit of the scaling factor.
		    If ''text-fit/grow'' is specified and the value is 100% or greater,
			it is the maximum scaling factor.
		    If ''text-fit/shrink'' is specified and the value is between 0% and
			100% inclusive, it is the minimum scaling factor.
		    Otherwise, or if this component is omitted, there is no limit on
			the scaling factor.
		</dd>
	</dl>

	<p>This property provides a functionality to make [=inline-level=] contents
	exactly fill the inline size of the [=line box=].
	Unlike ''text-align/justify'' of the 'text-align' property, which achieves
	this by adjusting spacing between characters, this property scales the
	font size.

	<p>When ''text-fit/grow'' or ''text-fit/shrink'' is specified,
	a [=line scaling factor=] is computed for each [=line box=].
	If ''text-fit/consistent'' applies, all [=line boxes=] are scaled by the
	smallest computed [=line scaling factor=].
	Otherwise, each [=line box=] is scaled by its own [=line scaling factor=].

	<p>This property does not affect the 'font-size' [=computed value=],
	and thus does not affect font-size-relative <<length>> values of other properties.
	For example, "line-height: 1.5em" and "letter-spacing: 0.1em" are not
	affected by this scaling.

	<p>The [=used value=] of the text 'font-size' is its [=computed value=]
	multiplied by the [=line scaling factor=].

	<p>Scaling can change the [=block size=] of a [=line box=],
	which can in turn change its position along the [=block-axis=].
	If any feature is active that would cause the [=inline size=] of the
	[=line box=] to change based on its [=block-axis=] position	(such as
	'float' or 'initial-letter'), scaling is disabled for the block.

	<div class="issue">
		If the [=inline size=] of a block container depends on the size of
		the viewport, its apparent [=inline size=] may not change even if
		the user changes the page zoom level.
		In that case, if text is fitted with this feature, the text size may
		not change at all even though the zoom level has changed.
		There is no agreement yet on how to deal with this issue. See
		<a href="https://github.com/w3c/csswg-drafts/issues/12886">csswg#12886</a>.
	</div>

	<h4 id="text-fit-scaling-factor">Computing line scaling factor</h4>

	<p>The parts of the [=line box=]'s contents that can be scaled by this
	property are called <dfn>scalable parts</dfn>.
	These include:

	<ul>
		<li>
			Text, including text in [=inline boxes=], but excluding trailing
			white space.

		<li>
			Spacing whose [=inline size=] is proportional to the 'font-size'
			used value.
			E.g. percentage-based 'letter-spacing' or 'word-spacing', and 'text-autospace'.
	</ul>

	<p class="note">
	'text-indent', 'line-padding', non-percentage-based 'letter-spacing' and
	'word-spacing',	and [=atomic inlines=] are not [=scalable parts=].
	The [=inline-axis=] 'padding', 'border', and 'margin' of inline boxes are
	also not [=scalable parts=].

	<p>A <dfn>line scaling factor</dfn> is the ratio by which the
	[=scalable parts=] of a line must be scaled in order to make its
	[=inline-level=] content exactly fit the [=line box=]’s [=inline size=].

	<p>A [=line scaling factor=] is computed from:

	<ul>
		<li>The total [=inline size=] of the [=scalable parts=] in the line.
		<li>
			The remaining space in the [=line box=], including any trailing whitespace
			(which may be negative if the content overflows the [=line box=]).
	</ul>

	<p>If a <<percentage>> is specified, it clamps the [=line scaling factor=].

	<p class="note">
	A simple calculation for the [=line scaling factor=] would be
	<code>(A + B) / A</code>, where A is the total [=inline size=] of
	[=scalable parts=] and B is the remaining space.
	However, due to [[css-fonts-4#font-optical-sizing-def|optical sizing]], the
	[=inline size=] of text might not be perfectly proportional to its
	'font-size'.
	The exact method for determining a reasonable [=line scaling factor=]
	is up to the implementation.

	<p>The [=line scaling factor=] for a [=line box=] with no
	[=scalable parts=] is 1.


<h2 class="no-num" id="order">
Appendix A:
Text Processing Order of Operations</h2>

	* [[#text-fit-property|text fitting]] is applied
		after text wrapping and before text justification.
		* <a href="https://www.w3.org/TR/css-fonts-3/">font/glyph selection
			and positioning</a> [[!CSS-FONTS-3]] may be done again
		* 'letter-spacing', 'word-spacing', and 'text-spacing' may be updated.

<h2 class="no-num" id="acknowledgements">
Acknowledgements</h2>

	<wpt title="Tests not needed for this section."></wpt>

	The 'text-fit' property would not be here without the efforts of
	Kent Tamura and Roman Komarov.

<h2 class="no-num" id="changes">
Changes</h2>


<h3 class="no-num" id="changes-L3">
Additions Since Level 4</h3>

	New features in Level 5:
	* Added the 'text-fit' property.
