Page MenuHomePhabricator

Typography: address discrepancies in sans-serif font families across Codex and beyond
Open, HighPublicBUG REPORT

Description

Background

In Codex, where font-family tokens intended to be used in MediaWiki are defined, there are 3 sans-serif option tokens defined:

  • sans-10 which includes a comment for it to be used as a fallback.
    • "value": "sans-serif"
  • sans-50 which is deprecated.
    • "value": "'Helvetica Neue', 'Helvetica', 'Liberation Sans', 'Arial', sans-serif"
  • sans-100 which includes a font stack that is tailored to provide better operating system-specific readability.
    • "value": "-apple-system, 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Inter', 'Helvetica', 'Arial', sans-serif"

sans-100 is the font stack that is intended to be used. It is optimized to work best for various operating systems. However, at the application token level, font-family-base is set to sans-10 and not sans-100, whereas font-family-serif, the intended serif font stack to be used is set to serif-100, the serif equivalent to sans-100, optimized for various systems.

Anywhere that font-family is set in Codex, it is primarily set to inherit, except in the typography mixins in typography.less, where the sans-serif mixins set the font-family to @font-family-base. It does this to match the fonts used in Vector. These sans-serif mixins are used in a few components which contain more body text type of content, such as in Accordion, Dialog, and TextArea. The fact that these use both text that inherits its font-family and these mixins, it means that on the Codex docs site where the font-family is set to @font-family-systems-sans, and potentially other places, there is a discrepancy of sans serif fonts used within the same component. Anything coming from Codex, including typography mixins, should only ever set font-family to inherit, so that wherever it may be used, it has the same font family as the rest of the interface. OOUI does this already.

Vector sets the sans-serif font-family as such:

// Body content uses the user setting in browser / the system default sans-serif font:
// Arial on Windows, Roboto on Android.
// FIXME: Use Codex's OS specific default sans-serif fonts.
@font-family-sans: @font-family-sans--fallback; // Codex: 'Helvetica Neue', 'Helvetica', 'Liberation Sans', 'Arial', sans-serif;

Here, Vector is using @font-family-sans but setting to the Codex token @font-family-sans--fallback. There's a note here to change this, to essentially be using the sans-100 font stack as mentioned before, which optimizes for OS specific readability. To do this in its current state, it would need to use the @font-family-systems-sans token. However, the @font-family-base token implies through its name that it should be the default, or primarily used, sans-serif token used, even if it is the same font stack as the @font-family-systems-sans token. So what needs to happen here is in Codex we need to change the value of @font-family-base to point to @font-family-systems-sans. We then need to change the Codex token that is referenced in Vector to @font-family-base.

Minerva sets the sans-serif font-family to @font-family-base on the body element, but it also creates its own @font-family-base token, which is set to @font-family-systems-sans. So Minerva is using the intended, or correct, font stack, and sort of using the correct token. It just has to set a custom value to the -base token to get the right font stack. Once we change the value of @font-family-base to point to @font-family-systems-sans in Codex, then we can simply remove the custom value in Minerva.

Goal

Unify the way that systems define a sans-serif font-family, which is to inherit and unify the Codex token that Vector and Minerva use to ensure the same sans-serif font stack and token usage.

Acceptance criteria

  • Remove whatever barriers we have to using the stack from @font-family-system-sans
  • Update @font-family-base to use font-family.sans-100 in Codex application.json
  • Update Codex docs site to use @font-family-base
  • Update the Codex typography mixins which reference a sans-serif typeface to use inherit instead
  • Update Codex components to explicitly use @font-family-base except for Accordion, Card, Link, Table
  • Update Vector to use @font-family-base
  • Remove the custom @font-family-base token in Minerva as it is no longer needed.
  • @font-family-sans--fallback  is there as a fallback option if anyone really wants to use just sans-serif for something
  • Add comments to each of these tokens explaining their use case to guide people

Event Timeline

DTorsani-WMF triaged this task as High priority.

I see in T392842 that the typography mixins were changed from the deprecated @font-family-sans to @font-family-base...I'm struggling to remember the details of why, but I wanted to check on this before we change it again. cc @Volker_E who may remember the nuances here better than I do

I would assume that @font-family-base should be the default font family for most things, including our typography mixins. Maybe we can add some comments to the font family tokens to help ourselves and others understand when to use which token?

I've updated the task description to hopefully provide some more clarity on what's going on and what we want to do.

DTorsani-WMF renamed this task from Typography: update type mixins to reference system font family to Typography: address discrepancies in font-families across Codex and beyond.Feb 26 2026, 6:08 PM
DTorsani-WMF updated the task description. (Show Details)

To lighten up this divergence historically:

  1. the OS stack @font-family-system-sans: -apple-system, 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Inter', 'Helvetica', 'Arial', sans-serif, preferred from Design System point of view, has resulted in some unintended side-effects and community confusion once tried.
  2. In MinervaNeue it has had the biggest impact with least community slashback, hence we tried to include it there early.
  3. For certain environments (not only, but also Vector) @font-family-sans--fallback: sans-serif was important to provide to be error-safe.
  4. Deprecated @font-family-sans: 'Helvetica Neue', 'Helvetica', 'Liberation Sans', 'Arial', sans-serif was the historic alternative to more modern @font-family-system-sans
  5. We've never had the time to really pull the trigger on making Vector follow the OS stack due to needed involvement of community liasons and a process to make community understand its improvement with other design priorities in bigger need, but that has still been the outset design system goal.
Volker_E renamed this task from Typography: address discrepancies in font-families across Codex and beyond to Typography: address discrepancies in sans-serif font families across Codex and beyond.Mar 5 2026, 3:34 PM
Volker_E added a project: Design.
Volker_E updated the task description. (Show Details)

Thanks @Volker_E. Can you share more about what the unintended side effects and community confusion from #1? For #5, what type of community involvement do you feel we need at this point to move this forward? Essentially, how can we most effectively complete this task?

Before answering your first question, I want to start outlining best way to untangle this historic hairball:
My 1. attempt would be to remove the deprecated font-family-sans as it's a duplication of font-family-sans--fallback to simplify the conversation. I'd add this as acceptance criteria here. Refer also to T331403: Replace legacy value tokens in Codex, OOUI and downstream; originated in WikimediaUI Base
If we look at the current usages in Wikimedia deployed places Vector "typography.less' and print stylesheets in both, legacy and Vector 2022 are the only places where it's in use.

  • One idea was to have a print font-family token (actually a number of tokens separate from screen tokens, but that would mean a bigger change and I don't see the budget right now.
  • We could also replace the deprecated token with the new equal value token --fallback in print stylesheets with a comment about future print tokens task, and consider evaluating base token vs sans token value in typography.

Note, that we would need to touch both, legacy and Vector 2022, which product leads have to be informed about. All under the impression, that we don't aim for instant change, but for tech debt cleanup.

@Volker_E Wouldn't it be simpler to include this as a follow up task? All of the current acceptance criteria is doable with that step, and can be done before that step. This feels like it inflates the scope.

@DTorsani-WMF In my experience it's simpler to reduce similarities before going into making design and code impactful changes in order for orienting reviewers faster and gathering acceptance for such changes. But it's just a proposal from me.

Change #1248651 had a related patch set uploaded (by VolkerE; author: VolkerE):

[mediawiki/skins/Vector@master] styles, print: Replace deprecated `@font-family-sans` token

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

Change #1248654 had a related patch set uploaded (by VolkerE; author: VolkerE):

[mediawiki/skins/Vector@master] styles: Replace deprecated `@font-family-sans` token with correct one

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

@Volker_E makes sense, we just have to be a little more intentional about the scope of things these days with the limited resources we have. Thanks for helping out and submitting those two patches. What do you think is the best next step then?

Change #1248922 had a related patch set uploaded (by VolkerE; author: VolkerE):

[mediawiki/skins/MonoBook@master] styles: Replace deprecated `@font-family-sans` token with correct one

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

Change #1248955 had a related patch set uploaded (by VolkerE; author: VolkerE):

[mediawiki/skins/Mirage@master] styles: Replace deprecated `@font-family-sans` token with correct one

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

Change #1248963 had a related patch set uploaded (by VolkerE; author: VolkerE):

[design/codex@main] [BREAKING CHANGE] tokens: Remove deprecated `font-family-sans`

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

@DTorsani-WMF For completion: there was one more thought about the token structure back then. There might be skins, that want to have serif as default. So we would define both a serif choice and a sans-serif choice that is not the fallback sans-serif but something like 'Helvetica Neue', 'Helvetica', 'Liberation Sans', 'Arial', sans-serif;. And reference this in the font-family-base.
The deprecation came mainly out of downstream users getting it wrong and directly referencing font-family-sans instead of base.

We could also follow this logic and just remove the downstream usages and stop -sans from being exported.

To the other pieces and questions here:

  • From a rollout perspective, I'd suggest to change MinervaNeue again first, as it's a mostly readers focussed change and gather feedback there. Let's also not be to scared about this change there, as the readability for majority of users would benefit. Additionally, sans-serif is also a vague container, that differs per system.
  • On inherit: I vaguely remember some browser quirks on form elements many years ago, that might not explain our different approach. For me it's important thought to be clear about the design implications of only relying on inherit. When a Codex button would be placed within a heading, it would suddenly be serif in our current rendering. I could imagine that we want certain design system choices to be set explicitely. Remember, when a skin sets font-family-base to something different, that's an explicit choice. Having a button inherit the font family from the surrounding container is an implicit choice and in my opinion not good for user expectation and consistency.

The patches should have been on a sub-task, visualizing how many different inconsistent angles have accumulated in Codex and tokens application downstream:
Other just discovered issue is that CdxTooltip (+its demo) and WordbreakDemo both use system-sans without further explanation/documentation.

Change #1248955 merged by jenkins-bot:

[mediawiki/skins/Mirage@master] styles: Replace deprecated `@font-family-sans` token with correct one

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

@Volker_E thanks for all the additional information.

For Minerva, when you say "changing this first", are you referring to removing the custom setting of @font-family-base to @font-family-system-sans? We can't do this until we the second acceptance criteria item.

Regarding your note on inherit, this is a good point, but currently in Codex, we rarely are setting a font-family on components to anything other than inherit. So are you suggesting we should explicitly set font-family on all components to @font-family-base once we do the second acceptance criteria item?

Change #1248651 merged by jenkins-bot:

[mediawiki/skins/Vector@master] styles, print: Replace deprecated `@font-family-sans` token

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

Change #1248654 merged by jenkins-bot:

[mediawiki/skins/Vector@master] styles: Replace deprecated `@font-family-sans` token with correct one

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

@Volker_E thanks for all the additional information.

For Minerva, when you say "changing this first", are you referring to removing the custom setting of @font-family-base to @font-family-system-sans? We can't do this until we the second acceptance criteria item.

Reminder 2nd acceptance criteria is "Update @font-family-base to point to @font-family-system-sans"
That's not quite true. The tokens system in MediaWiki enables us to set certain properties specifically for skins, so we can set Minerva Neue to the OS specific sans-serf.

Regarding your note on inherit, this is a good point, but currently in Codex, we rarely are setting a font-family on components to anything other than inherit. So are you suggesting we should explicitly set font-family on all components to @font-family-base once we do the second acceptance criteria item?

It's necessary to consider in my opinion as it's less error-prone in our environment and provides more consistent usage flexibility on components (inject a component into a serif parent). The only time where I would consider differently across skins are Link, Breadcrumb, Accordion, Container, Card, Table. All others are in my font family choice power understanding maximally to override by a skin.

On another digging through memory/git logs: As stated above, we've had used the OS font stack in MinervaNeue since back 5 years ago

With the introduction of Codex design tokens as replacement and internal discussions to set it accordingly for both, Vector and MinervaNeue (Vector 2022 launched about the same time as the Codex design tokens as mediawiki.skin.variables.less architecture and I vaguely remember that we wanted to identify using the OS stack on Vector 2022 (TypeaheadSearch was one of the pillars there) after dust has settled.

Instead of relying on a font-family-base skin variables override MinervaNeue is setting the OS stack in the old 'minerva.variables.less' file. That's a confusing historic piece and I'll tackle that immediately in a patch.

@Volker_E thanks for your help on this. Forgive me about the second criteria, that wasn't as clear as it should've been. I've updated it, as it is specifically for in Codex, and we could either update @font-family-base to point to @font-family-system-sans or font-family.sans-100 in Codex application.json. Which do you think is best?

I'm happy to put together a patch in Codex updating components, except those you listed, to explicitly use @font-family-system-sans. Additionally, I imagine we might still want to update the Codex typography mixins which reference a sans-serif typeface to use inherit instead. This way, whether they are used in components or somewhere downstream, they will inherit the appropriate parent font-family. What do you think?

Change #1250760 had a related patch set uploaded (by Dtorsani; author: Dtorsani):

[design/codex@main] Update font-families used in components

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

Change #1248922 merged by jenkins-bot:

[mediawiki/skins/MonoBook@master] styles: Replace deprecated `@font-family-sans` token with correct one

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