Page MenuHomePhabricator

Discuss how to handle font-size tokens in different skins with different base font sizes
Open, Stalled, MediumPublic5 Estimated Story Points

Description

The way font-size tokens work now

Codex internally defines the values of the various font-size tokens in pixels. For example, font-size-large is defined as 18px. But the value that is actually output for this token and is used in practice (both in CSS for Codex's own components, and for consuming code that uses @font-size-large or var( --font-size-large ) in its own Less or CSS), is first transformed to ems. This transformation is based on the base font size for the skin we're targeting. Codex generates two different token outputs, for two different base font sizes: 16px (the default; used in Minerva) and 14px ("legacy"; used in Vector). When a font-size token is transformed from pixels to ems, the transformation is done such that the resulting pixel value is the same. For example, font-size-large is defined as 18px, so in the default output it's 1.125em (assuming a 16px base font size that's 1.125 * 16 = 18px) and in the legacy output it's 1.285714 (assuming a 14px base font size that's 1.285714 * 14 = 18px).

Token nameInternal definitionDefault outputPixel value in default skinsLegacy outputPixel value in legacy skins
font-size-x-small12px0.75em0.75 * 16 = 12px0.8571429em0.8571429 * 14 = 12px
font-size-small14px0.875em0.875 * 16 = 14px1em1 * 14 = 14px
font-size-medium16px1em1* 16 = 16px1.1428571em1.1428571 * 14 = 16px
font-size-large18px1.125em1.125 * 16 = 18px1.2857143em1.2857143 * 14 = 18px
font-size-x-large20px1.25em1.25 * 16 = 20px1.4285714em1.4285714 * 14 = 20px
font-size-xx-large24px1.5em1.5 * 16 = 24px1.7142857em1.7142857 * 14 = 24px
font-size-xxx-large28px1.75em1.75 * 16 = 28px2em2 * 14 = 28px

This same technique of computing the number of ems to arrive at the same number of pixels regardless of the base font size is helpful for the size tokens, which are conceptually absolute but are implemented using ems to support text zooming. But doing this for font-size tokens causes issues like T357964: Dialog: fix the text size in the dialog's title on Desktop and T357965: Accordion: fix the label size on dekstop where the font size of certain elements of components is out of step with the font size of the surrounding text. For example, the Dialog component uses font-size-large for its header, which means the header is always 18px. This means that relative to the font size of regular text, it looks bigger in Vector (18px vs 14px) than in Minerva (18px vs 16px).

The way line-height tokens work now

Meanwhile, the line-height tokens are defined as relative values: they are multiples of the font size. For example, line-height-xx-small is defined as 1.375, meaning the line height will be 1.375x the font size, whatever the font size is. For text with a 16px font size that works out to 22px; for text with a 14px font size it's 19.25px. This means line-heights aren't always round numbers of pixels, especially in legacy skins. Note that the line height is relative to the font size of the specific line of text it's applied to, not to the base font size, so e.g. line-height-xxx-small (1.25) is 20px when applied to regular text (font size 16px), but 22.5px when applied to a dialog header where the font size is 18px.

Token nameInternal definitionDefault outputPixel value for normal text in default skinsLegacy outputPixel value for normal text in legacy skins
line-height-xxx-small1.251.251.25 * 16 = 20px1.251.25 * 14 = 17.5px
line-height-xx-small1.3751.3751.375 * 16 = 22px1.3751.375 * 14 = 19.25px
line-height-small1.57142851.57142851.5714285 * 16 = 25.14285px1.57142851.5714285 * 14 = 22px
line-height-medium1.61.61.6 * 16 = 25.6px1.61.6 * 14 = 22.4px
Option 0: Keep everything the way it is

If we decide that the font size of e.g. a dialog header should always be the same pixel value regardless of the font size of the surrounding text, then the way things work now is fine, and we don't need to change anything.

Option 1: Make font-size tokens relative

We could define font-size tokens as relative values that are multiples of the base font size. (This is somewhat similar to how line-height tokens work, except that line-height is relative to the font size of the text it's applied to, which may be different from the base font size.) For example, we could say that font-size-large should always be 1.125x the base font size, meaning that it would be 18px in default skins (where the base font size is 16px) but 15.75px in legacy skins (where the base font size is 14px). This way, a dialog header for example would be approximately 2px larger than the surrounding text in both skins.

The full list of font-size values would be:

Token nameInternal definitionDefault outputPixel value in default skinsLegacy outputPixel value in legacy skins
font-size-x-small0.75em0.75em0.75 * 16 = 12px0.75em0.75 * 14 = 10.5px
font-size-small0.875em0.875em0.875 * 16 = 14px0.875em0.875 * 14 = 12.25px
font-size-medium1em1em1* 16 = 16px1em1em * 14 = 14px
font-size-large1.125em1.125em1.125 * 16 = 18px1.125em1.125 * 14 = 15.75px
font-size-x-large1.25em1.25em1.25 * 16 = 20px1.25em1.25 * 14 = 17.5px
font-size-xx-large1.5em1.5em1.5 * 16 = 24px1.5em1.5 * 14 = 21px
font-size-xxx-large1.75em1.75em1.75 * 16 = 28px1.75em1.75 * 14 = 24.5px
Option 2: Pick different values for font-size tokens for different base font sizes

We could define the values of each of these font-size tokens for default skins and legacy skins separately. This would allow us to achieve something like option 1, but instead of sticking exactly to the same multipliers, we could tweak the values (e.g. to make them round numbers).

With this approach, an example list of font sizes could be:

Token nameInternal definitionDefault outputPixel value in default skinsLegacy outputPixel value in legacy skins
font-size-x-small12px / 10px0.75em0.75 * 16 = 12px0.7142857em0.7142857 * 14 = 10px
font-size-small14px / 12px0.875em0.875 * 16 = 14px0.8571429em0.857129 * 14 = 12px
font-size-medium16px / 14px1em1* 16 = 16px1em1em * 14 = 14px
font-size-large18px / 16px1.125em1.125 * 16 = 18px1.1428571em1.1428571 * 14 = 16px
font-size-x-large20px / 18px1.25em1.25 * 16 = 20px1.2857143em1.2857143 * 14 = 18px
font-size-xx-large24px / 20px1.5em1.5 * 16 = 24px1.4285714em1.4285714 * 14 = 20px
font-size-xxx-large28px / 24px1.75em1.75 * 16 = 28px1.7142857em1.7142857 * 14 = 24px

Note that the internal definitions of these font sizes would be in pixels that are then transformed to ems (like option 0, and unlike option 1). These tokens would be defined with different values for the default theme vs the legacy theme; no other tokens currently do this, so we would need to make some changes to the tokens code to support this.

Augmentation A: use rems instead of ems

Separately from the options above (regardless of whether we choose option 0, 1 or 2), we could output values expressed in rem instead of em. In (almost) all MediaWiki skins, the root element's font size is 16px, even if the base font size is something else (the base font size is set on a different element, not the root element). This means that 1rem always means 16px. Using rems would allow us to simplify the transformation and make it independent of the base font size that is used (instead we just need to divide the pixel value by 16), while still technically using a relative unit so that text zooming is still supported.

For example, font-size-large would be 1.125rem in the default output, and in the legacy output it would be 1.125rem (if we want it to be 18px, like in option 0) or 0.984375rem (if we want it to be 15.75px, like in option 1) or 1rem (if we want it to be 16px, like in option 2). All of these are just the desired pixel value divided by 16.

Doing this requires changing "almost all MediaWiki skins" to "actually all MediaWiki skins", which is captured in T343316: Promote `rem` technical requirements across themes.

The proof of concept patch for this approach combines rems with option 0.

Event Timeline

CCiufo-WMF triaged this task as Medium priority.Feb 20 2024, 6:46 PM
Catrope renamed this task from PLACEHOLDER: Discuss how to handle font-size tokens in different skins with different base font sizes to Discuss how to handle font-size tokens in different skins with different base font sizes.Feb 21 2024, 1:15 AM
Catrope updated the task description. (Show Details)

Change 1005580 had a related patch set uploaded (by Eric Gardner; author: Eric Gardner):

[design/codex@main] [PoC, DNM] tokens: explore using rem values for font-size

https://gerrit.wikimedia.org/r/1005580

Test wiki created on Patch demo by EGardner (WMF) using patch(es) linked to this task:
https://patchdemo.wmflabs.org/wikis/c913d31ad4/w

Change 1005582 had a related patch set uploaded (by Eric Gardner; author: Eric Gardner):

[mediawiki/core@master] [PoC, DNM] Codex: test out rem-based typography on wiki pages

https://gerrit.wikimedia.org/r/1005582

Change 1005631 had a related patch set uploaded (by Eric Gardner; author: Eric Gardner):

[mediawiki/skins/Vector@master] icons: restore "background-" CSS rules

https://gerrit.wikimedia.org/r/1005631

Catrope updated the task description. (Show Details)
CCiufo-WMF changed the task status from Open to In Progress.Feb 29 2024, 5:27 PM
CCiufo-WMF assigned this task to egardner.

Change 1007984 had a related patch set uploaded (by Eric Gardner; author: Eric Gardner):

[design/codex@main] build, tokens: treat "legacy" font size as a mode

https://gerrit.wikimedia.org/r/1007984

One thing to keep in mind with treating "legacy" as mode: there are already theme-wikimedia-ui-legacy.less files in use in Translate and Universal Language Selector extensions since regards to removing 'mediawiki.ui' vars.
This file was meant to be updated continuously in the extensions needing them. With the modes, we have to change what we're providing there. Reason for putting them there was that we wanted the two with their old MediaWiki support pre v1.38. As we're talking Translate seems to be adapted to use skin vars, so it's a one extension only issue.

Change 1005580 abandoned by Eric Gardner:

[design/codex@main] [PoC, DNM] tokens: explore using rem values for font-size

Reason:

This patch has been superseded by https://gerrit.wikimedia.org/r/c/design/codex/+/1007984

https://gerrit.wikimedia.org/r/1005580

Change 1007984 merged by jenkins-bot:

[design/codex@main] build: Make "legacy" build redundant

https://gerrit.wikimedia.org/r/1007984

@CCiufo-WMF I think we should move this task to the backlog Up Next. This is a subset of the font-size decisions we need to make, and recent discussions have led us to pursue options for desired design behavior first, which can then be followed by deciding how to implement the behavior. Handling font-size tokens is part of that latter decision. We may want to find another way to represent the font-size discussion work on our sprint boards, but IMO this task is specific to one decision and can be backlogged for now. I'm hoping we can get back to it in a sprint or two, once we've made more headway on the design decisions.

@AnneT that sounds good. I think we need a new epic to encapsulate this work, with this being just one of the subtasks.

CCiufo-WMF added a subscriber: AnneT.

Change #1016452 had a related patch set uploaded (by Catrope; author: Catrope):

[mediawiki/core@master] Update Codex from v1.3.5 to v1.3.6

https://gerrit.wikimedia.org/r/1016452

Change #1016452 merged by jenkins-bot:

[mediawiki/core@master] Update Codex from v1.3.5 to v1.3.6

https://gerrit.wikimedia.org/r/1016452