CSS Font Display Controls Module Level 1

Unofficial Proposal Draft,

This version:
https://tabatkins.github.io/specs/css-font-display/
Issue Tracking:
Inline In Spec
GitHub Issues
Editors:
Tab Atkins (Google)
Kenji Baheux (Google)
Suggest an Edit for this Spec:
GitHub Editor
This Document Is Obsolete and Has Been Replaced

This specification is obsolete and has been replaced by the document at https://drafts.csswg.org/css-fonts-4/#font-display-desc. Do not attempt to implement this specification. Do not refer to this specification except as a historical artifact.


Abstract

This spec introduces a new @font-face descriptor for controlling how a downloadable font renders before it is fully loaded. It’s intended that this spec be merged into the Fonts spec, likely Fonts Level 4.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, in speech, etc.

Status of this document

1. Introduction

When using downloadable webfonts via @font-face, the user agent needs to know what to do while the font is actively loading. Most web browsers have adopted some form of timeout:

Browser Timeout Fallback Swap
Chrome 35+ 3 seconds yes yes
Opera 3 seconds yes yes
Firefox 3 seconds yes yes
Internet Explorer 0 seconds yes yes
Safari 3 seconds yes yes

While these default behaviors are reasonable, they’re unfortunately inconsistent across browsers. Worse, no single approach is sufficient to cover the range of use-cases required by modern user-experience– and performance–conscious applications.

The Font Loading API [CSS-FONT-LOADING-3] allows a developer to override some of the above behaviors, but that requires scripting, a non-trivial amount of effort, and ultimately doesn’t provide sufficient hooks to cover all reasonable cases. Additionally, the developer needs to either inline the loading script into their page or load an external library, introducing additional network latency before the fonts can be loaded and delaying text rendering.

Design/performance-conscious web developers have a good sense for the relative importance of a given web font for the intended user experience. This specification provides them the ability to control font timeout and rendering behavior. Specifically, it lets developers:

2. The Font Display Timeline

At the moment the user agent first attempts to use a given downloaded font face on a page, the font face’s font download timer is started. This timer advances through three periods of time associated with the font face—the block period, the swap period, and the failure periodwhich dictate the rendering behavior of any elements using the font face:

To render with a fallback font face for a given element, the user agent must find the first font face specified in the element’s font-family list which is already loaded, and use that for rendering text. Doing this must not trigger loads of any of the fallback fonts.

To render with an invisible fallback font face for a given element, find a font face as per "render with a fallback font face". Create an anonymous font face with the same metrics as the selected font face but with all glyphs "invisible" (containing no "ink"), and use that for rendering text. Doing this must not trigger loads of any of the fallback fonts.

fallback and optional can result in some faces in a family being used while others are required to fallback, giving a "ransom note" look. Perhaps require that all fonts in a family have the same behavior (all swapped in, or all fallback)? See also the @font-feature-values for controlling the behavior on a font family basis.

3. Controlling Font Display Per Font-Face: the font-display descriptor

The font-display descriptor for @font-face determines how a font face is displayed, based on whether and when it is downloaded and ready to use.

Name: font-display
For: @font-face
Value: auto | block | swap | fallback | optional
Initial: auto

Note: For all of these values, user agents may use slightly different durations, or more sophisticated behaviors that can’t be directly expressed in the font-display syntax, in order to provide more useful behavior for their users. They may also provide the ability for users to override author-chosen behavior with something more desirable; for example, forcing all fonts to have a 0s block period.

auto
The font display policy is user-agent-defined.

Note: Many browsers have a default policy similar to that specified by block.

block
Gives the font face a short block period (3s is recommended in most cases) and an infinite swap period.

Note: In other words, the browser draws "invisible" text at first if it’s not loaded, but swaps the font face in as soon as it loads.

This value must only be used when rendering text in a particular font is required for the page to be usable. It must only be used for small pieces of text.

For example, badly designed "icon fonts" might associate a "⎙" (print) icon with an unrelated character like "C", so if the text is displayed with a fallback font instead there will be confusing letters scattered around the page rather than the desired icon. In this case, temporary blank spots are better than using a fallback font.

(However, the fallback font is used eventually, as having confusing letters scattered around the page is better than having links and such never show up at all.)

swap
Gives the font face a 0s block period and an infinite swap period.

Note: In other words, the browser draws the text immediately with a fallback if the font face isn’t loaded, but swaps the font face in as soon as it loads.

This value should only be used when rendering text in a particular font is very important for the page, but rendering in any font will still get a correct message across. It should only be used for small pieces of text.

For example, if a website has a custom font for rendering their logo, rendering that logo correctly is fairly important for branding purposes, but displaying the logo in any font will at least get the point across without confusion.
fallback
Gives the font face an extremely small block period (100ms or less is recommended in most cases) and a short swap period (3s is recommended in most cases).

Note: In other words, the font face is rendered with a fallback at first if it’s not loaded, but it’s swapped in as soon as it loads. However, if too much time passes, the fallback will be used for the rest of the page’s lifetime instead.

This value should be used for body text, or any other text where the use of the chosen font is useful and desired, but it’s acceptable for the user to see the text in a fallback font. This value is appropriate to use for large pieces of text.

For example, in large pieces of body text, it’s most important just to get the text rendered quickly, so the user can begin to read as quickly as possible. Further, once the user has started reading, they shouldn’t be disturbed by the text suddenly "shifting" as a new font is swapped in, as that’s distracting and annoying to re-find where one was in the text.
optional
Gives the font face an extremely small block period (100ms or less is recommended in most cases) and a 0s swap period.

If the font is not retrieved before the two durations expire, the user agent may choose to abort the font download, or download it with a very low priority. If the user agent believes it would be useful for the user, it may avoid even starting the font download, and proceed immediately to using a fallback font.

Note: In other words, the font is used if it’s already downloaded and available, but otherwise a fallback is used for the rest of the page’s lifetime instead. The font might download in the background and be available to future page loads, but if the user-agent detects that the user has very limited bandwidth, it might choose to simply never download and use the font.

This value should be used for body text, or any other text where the chosen font is purely a decorative "nice-to-have". It should be used anytime it is more important that the web page render quickly on first visit, than it is that the user wait a longer time to see everything perfect immediately.

For example, body text is perfectly readable in one of the browser default fonts, though a downloadable font face may be more attractive and mesh with the site’s aesthetics better. First time visitors to a site generally care far more about the site being quickly usable than they do about the finer points of its display, and optional provides a good behavior for them. If they return later, the desired font faces might have finished downloading, giving them the "intended" experience without slowing down either their first or subsequent visits.

Users on very slow connections might not ever receive the "intended" experience, but optional ensures they can actually use the site, rather than quitting and going elsewhere because the site takes too long to load.

4. Controlling Font Display Per Font-Family via @font-feature-values

The font-display descriptor for @font-feature-values determines how a font family is displayed, by setting the "default" font-display value for @font-face rules targeting the same font family. When font-display is omitted in an @font-face rule, the user agent uses the font-display value set via the @font-feature-values/font-display for the relevant font-family if one is set, and otherwise defaults to "font-display: auto".

This mechanism can be used to set a default display policy for an entire font-family, and enables developers to set a display policy for @font-face rules that are not directly under their control. For example, when a font is served by a third-party font foundry, the developer does not control the @font-face rules but is still able to set a default font-display policy for the provided font-family. The ability to set a default policy for an entire font-family is also useful to avoid the ransom note effect (i.e. mismatched font faces) because the display policy is then applied to the entire font family.

Name: font-display
For: @font-feature-values
Value: auto | block | swap | fallback | optional
Initial: auto
These names aren’t great. It would probably be better to use "intent" names that immediately capture the intended usage of each. Some suggestions:

5. Acknowledgements

Special thanks to Ilya Grigorik and David Kuettel for their help in developing this specification.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.

Conformance classes

Conformance to this specification is defined for three conformance classes:

style sheet
A CSS style sheet.
renderer
A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
A UA that writes a style sheet.

A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

Requirements for Responsible Implementation of CSS

The following sections define several conformance requirements for implementing CSS responsibly, in a way that promotes interoperability in the present and future.

Partial Implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported property values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

Implementations of Unstable and Proprietary Features

To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

Implementations of CR-level Features

Once a specification reaches the Candidate Recommendation stage, implementers should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec, and should avoid exposing a prefixed variant of that feature.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSS-FONTS-3]
John Daggett; Myles Maxfield; Chris Lilley. CSS Fonts Module Level 3. 14 August 2018. PR. URL: https://www.w3.org/TR/css-fonts-3/
[CSS-FONTS-4]
John Daggett; Myles Maxfield. CSS Fonts Module Level 4. 10 April 2018. WD. URL: https://www.w3.org/TR/css-fonts-4/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 14 August 2018. WD. URL: https://www.w3.org/TR/css-values-4/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119

Informative References

[CSS-FONT-LOADING-3]
Tab Atkins Jr.. CSS Font Loading Module Level 3. 22 May 2014. WD. URL: https://www.w3.org/TR/css-font-loading-3/

Property Index

No properties defined.

@font-face Descriptors

Name Value Initial
font-display auto | block | swap | fallback | optional auto

@font-feature-values Descriptors

Name Value Initial
font-display auto | block | swap | fallback | optional auto

Issues Index

fallback and optional can result in some faces in a family being used while others are required to fallback, giving a "ransom note" look. Perhaps require that all fonts in a family have the same behavior (all swapped in, or all fallback)? See also the @font-feature-values for controlling the behavior on a font family basis.
These names aren’t great. It would probably be better to use "intent" names that immediately capture the intended usage of each. Some suggestions: