Skip to content

[css-fonts] Proposal to extend CSS font-optical-sizing #4430

@Lorp

Description

@Lorp

Introduction

This proposal extends the CSS Fonts Module Level 4 font-optical-sizing property by allowing numerical values to express the ratio of CSS px units to the the units used in the opsz OpenType Font Variation axis. The ratio is intended to be multiplied by font-size, measured in px, allowing control over the automatic selection of particular optical size designs in variable fonts.

The proposal resolves the conflicting implementations of the font-optical-sizing: auto behaviour, and provides additional benefits for font makers, CSS authors, and end-users.

Examples

  • font-optical-sizing: 1.0; current Apple Safari behaviour where 1px = 1 opsz unit
  • font-optical-sizing: 0.75; Apple TrueType and OpenType behaviour where 1px = 0.75 opsz units (1px = 0.75pt in many user agents)
  • font-optical-sizing: 0.5; custom behaviour where 2px = 1 opsz unit, to “beef up” the text (e.g. in an accessibility mode for visually impaired end-users)
  • font-optical-sizing: 2.0; custom behaviour where 1px = 2 opsz units, to reduce the “beefiness” of the text (suitable for large devices)
  • font-optical-sizing: auto; use the font-optical-sizing ratio defined in the user agent stylesheet

Background

OpenType Font Variations in CSS

When the OpenType Font Variations extension of the OpenType spec was being developed in 2015–2016, Adam Twardoch and Behdad Esfahbod proposed the addition of the low-level font-variation-settings property to the CSS Fonts Module Level 4 specification, modeled after font-feature-settings.

For higher-level control of font variations, there was general consensus that the font-weight property would be tied to the wght font axis registered in the OpenType specification, font-stretch would be tied to wdth, while font-style would be tied to ital and slnt.

OpenType opsz variation axis and CSS font-size

The consensus was that the CSS font-size property could be tied to the axis registered for optical size, opsz. The opsz axis provides different designs for different sizes. Commonly, a lower value on the opsz axis yields a design that has wider glyphs and spacing, thicker horizontal strokes and taller x-height. The OpenType spec suggests that “applications may choose to select an optical-size variant automatically based on the text size”, and states: “The scale for the Optical size axis is text size in points”. Apple’s TrueType Variations specification (on which OpenType Font Variations is based) also mentions point size as the scale for interpreting the opsz axis: “'opsz', Optical Size, Specifies the optical point size.” It is notable that neither the OpenType spec nor Apple’s TrueType spec addresses the interpretation of opsz values in environments where the typographic point is not usefully defined.

Optical sizing introduces a new factor in handling text boxes in web documents. If the font size of a text box changes, the proportions of the box not remain constant because of the non-linear scaling of the font; typically the width grows at a slower rate than the height, because of the optical compensations in typeface design mentioned above. Realizing that many web documents may rely on the assumption of linear scaling, Twardoch proposed an additional CSS property font-optical-sizing:

  • value auto: “enables” optical sizing by tying the selection of a value on the opsz axis to the font size change
  • value none: “disables” optical sizing by untying that selection, so font size change happens linearly

The font-optical-sizing property is currently part of CSS Fonts Module Level 4 working draft.

Controversy: opsz axis and CSS font-size (px vs. pt)

Unfortunately recent browser developments introduced ambiguity in terms of how opsz values should be interpreted:

  • Most browser implementers interpret opsz as expressed in CSS pt units (points). If optical sizing is enabled, all text has its opsz axis set to the value of the font size in pt. [In fact, Chrome and Firefox, as well as Safari, interpret opsz in px units. Updated thanks to @drott’s comment below.]

  • Apple in Safari has decided to interpret opsz as expressed in CSS px units (pixels). If optical sizing is enabled, all text has its opsz axis set to the value of the font size in px.

  • Font makers and typographers are upset at Apple’s decision. They design fonts with the assumption that opsz is expressed in points. Since px values are commonly higher than pt values (typically at a ratio of 4:3) interpreting opsz in px means the that a higher optical size will be chosen than intended. For 9pt/12px text, the opsz design 12 will be chosen, which will yield text that is too thin, too tightly spaced, and potentially illegible. They argue that the user experience will degrade, and optical sizing will actually yield worse results than no optical sizing, effectively defeating the whole purpose and unjustly giving variable fonts bad reputation. Inconsistent behaviour with the same font will cause problems for font makers and CSS authors.

  • Apple defends this decision, suggesting that CSS authors can simply set font-variation-settings: 'opsz' n.

  • CSS authors object that using font-variation-settings breaks the cascade for font styling and, because of the nature of optical size, is unsuitable for application at the document root level. Therefore it will not get used.

Proposed resolution: numerical values in font-optical-sizing

The CSS font-optical-sizing property currently controls the relationship between font-size and opsz by means of a simple switch (auto/none). We propose to allow a numeric value for font-optical-sizing. This value expresses the ratio of opsz units to CSS px. Examples:

  • font-optical-sizing: 1.0; current Apple Safari behaviour where 1px = 1 opsz unit
  • font-optical-sizing: 0.75; Apple TrueType and OpenType behaviour where 1px = 0.75 opsz units (1px = 0.75pt in many user agents)
  • font-optical-sizing: 0.5; custom behaviour where 2px = 1 opsz unit, which would “beef up” the text (suitable for very small devices)
  • font-optical-sizing: 2.0; custom behaviour where 1px = 2 opsz unit, which would “reduce the beefiness” of the text (suitable for large devices)
  • font-optical-sizing: auto; use the font-optical-sizing ratio defined in the user agent stylesheet

Results

  • User agents can ship with default font-optical-sizing other than 1.0. (The CSS specification might recommend 0.75 as a reasonable default for most situations.)

  • Font makers can ship a single font whose opsz axis works as intended in browsers as well as print.

  • CSS authors can change the value whenever they like, independently of the choices made by browser vendors and font makers.

  • CSS authors can specify a different font-optical-sizing ratio for different media queries, including print, or for aesthetic purposes.

  • End-users can be offered accessibility modes that choose low values for font-optical-sizing to ensure lower-than-default opsz values and more legible text.

Note

  • This proposal does not introduce breaking changes. We believe that this is one of the rare cases where we can resolve the controversy amicably and provide additional benefits for all parties, while utilizing pre-existing mechanisms.
  • Key commits: WebKit Chromium Gecko

Proposers

  • Laurence Penney, OpenType Font Variations expert, author of Axis-Praxis.org, member of the MyFonts founding team
  • Adam Twardoch, Director of Products at FontLab, contributor to CSS Fonts, OpenType Font Variations and OpenType SVG

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions