The gist: Before using a mono typeface to improve the clarity of single line non-lexical strings, check available character alternatives in your base typeface. This can offer similar benefit, without needing to balance a differently-proportioned typeface.
I sometimes see interfaces take the following approach to text styling:
- Use a base sans-serif system typeface
- Present non-lexical strings (such as commit SHAs or UUIDs) in monospace
This works. Mono typefaces excel at disambiguating characters that can be difficult to distinguish, such as “ilIoO0”1. Plus it can add a nice, technical flair to the visual design.
But there are drawbacks. Most intuitively, the width of content set in a mono typeface scales linearly per character, compared to proportional sans-serif typefaces.
But more subtly: the greater the ratio of mono text in a sans-serif interface, the more the differences in optical qualities between the two begin to clash and feel unbalanced.
While both examples use identifical styles, the shorter commit SHA doesn’t feel as unbalanced with the surrounding sans-serif interface as longer git branch does.
You could try tweaking the size of monospace fonts to optically balance them.
.mono-correction { font-size: 0.95em;}
But for single line contexts, there are alternatives.
Some typefaces like Geist from Vercel have type design choices which blend technical character disambiguation styles similar to mono typefaces into the default character set.
But for even more control, many typefaces include alternative characters that can be activated, either for stylistic flair or where greater precisision is desired.
In CSS, this is achived with font-feature-settings
.
This allows you to enable specific opentype feature tags specified by the
typeface to render alternative characters available in the font.
.font-precise { font-feature-settings: 'ss02' 1;}
Compare with the monospace version, you get some of the legibility improvements provided by monospace, while maintaining balance with the rest of the interface:
Note the specific opentype feature tags vary between font families. Many have great documentation, here are a couple of opengraph feature tags available from Inter:
Property | Definition |
---|---|
ss02 | Disambiguation set |
cv05 | Lower-case L with tail |
cv08 | Upper-case i with serif |
zero | Slashed zero |
There’s many other features, a personal
favourite of mine in the Inter typeface is cv11
, which replaces the default
“a” glyph with a
single story “a”.
Applying with CSS
Depending on your project, you might choose one of two approaches for implementing:
- Globally: All text will render with the disambiguated character set. This might make sense if your product is highly technical. Great choice for marketing sites.
- Specifically: Add a utility class that activates disambiguation selectively for non-lexical strings, offering the benefit of monospace typefaces without the optical imbalance and per-character width scaling.
Applying globally
Globally with regular CSS
Use the font-feature-settings
rule and activate the desired alternatives.
body { font-feature-settings: 'ss02' 1;}
Globally with Tailwind 4
Use the font-*--font-feature-settings
custom property in your theme
configuration to activate alternative character variants for the corresponding
Tailwind font family utility class, such as font-sans
.
@theme { --font-sans: Inter, 'sans-serif'; --font-sans--font-feature-settings: 'ss02' 1;}
With a utility class
Regular CSS utility class
Create a class with the corresponding font-feature-settings activated.
@layer utilities { .font-precise { font-feature-settings: 'ss02' 1; }}
Tailwind utility class
Similar to above, but use the Tailwind @utility
directive.
@utility font-precise { font-feature-settings: 'ss02' 1;}
Conclusion
Your mileage (and preference) may vary, depending on the context of the product and the ratio of content rendered in monospace in your user interface. But it’s nice that so many of the typefaces we use day-to-day have these options, that can be enabled both for accessibility (and stylistic) flair!
Regardless, monospace still has its place. Particularly for multi-line code blocks where alignment between rows is desired. But for other contexts where you desire greater precision in a UI, check what alternatives your base typeface has, and in many cases a few small tweaks to your standard typeface might be all you need.
Improved precision with technical content is only one use-case of alternative typeface characters. Stylistic alternatives available through opentype feature tags open up opportunities for subtle distinction and differentiation too!
Footnotes
-
On a meta note, I applied Inter’s disambiguation stylistic alternative here specifically to distinctly render those characters. ↩