Superscripts and subscripts are important components in educational and scientific content material — from quotation references to chemical formulation and mathematical expressions. But browsers deal with these components with a static strategy that may create vital issues: components turn out to be both too small on cellular units or disproportionately giant on desktop shows.
After years of wrestling with superscript and subscript scaling in CSS, I’m proposing a contemporary resolution utilizing fluid calculations. On this article, I’ll present you why the static strategy falls quick and the way we are able to present higher typography throughout all viewports whereas sustaining accessibility. Better of all, this resolution requires nothing however clear, pure CSS.
The issue with static scaling
The scaling subject is especially evident when evaluating skilled typography with browser defaults. Take this instance (tailored from Wikipedia), the place the primary “2” is professionally designed and included within the glyph set, whereas the second makes use of <sub>
(prime) and <sup>
(backside) components:
Browsers have traditionally used font-size: smaller
for <sup>
and <sub>
components, which interprets to roughly 0.83x scaling. Whereas this made sense within the early days of CSS for easy paperwork, it may create issues in trendy responsive designs the place font sizes can fluctuate dramatically. That is very true when utilizing fluid typography, the place textual content sizes can scale easily between extremes.
Fluid scaling: A greater resolution
I’ve developed an answer that scales extra naturally throughout totally different sizes by combining mounted and proportional items. This strategy ensures legibility at small sizes whereas sustaining correct proportions at bigger sizes, eliminating the necessity for context-specific changes.
Right here’s the way it works:
sup, sub {
font-size: calc(0.5em + 4px);
vertical-align: baseline;
place: relative;
prime: calc(-0.5 * 0.83 * 2 * (1em - 4px));
/* Simplified prime: calc(-0.83em + 3.32px) */
}
sub {
prime: calc(0.25 * 0.83 * 2 * (1em - 4px));
/* Simplified prime: calc(0.42em - 1.66px) */
}
- Pure scaling: The degressive system ensures that superscripts and subscripts stay proportional in any respect sizes
- Baseline alignment: Through the use of
vertical-align: baseline
and relative positioning, we stop the weather from affecting line peak and it offers us higher management over the offset to match your particular wants. You’re in all probability additionally questioning the place the heck these values come from — I’ll clarify within the following.
Breaking down the maths
Let’s have a look at how this works, piece by piece:
px
)
Calculating the font measurement (At small sizes, the mounted 4px
part has extra impression. At giant sizes, the 0.5em
proportion turns into dominant. The result’s extra pure scaling throughout all sizes.
sup, sub {
font-size: calc(0.5em + 4px);
/* ... */
}
sub {
/* ... */
}
em
)
Calculating the mother or father font measurement (Throughout the <sup>
and <sub>
components, we are able to calculate the mother or father’s font-size
:
sup, sub {
font-size: calc(0.5em + 4px);
prime: calc(2 * (1em - 4px));
}
sub {
prime: calc(2 * (1em + 4px));
}
The fluid font measurement is outlined as calc(0.5em + 4px)
. To compensate for the 0.5em
, we first want to unravel 0.5em * x = 1em
which provides us x = 2
. The 1em
right here represents the font measurement of the <sup>
and <sub>
components themselves. We subtract the 4px
mounted part from our present em
worth earlier than multiplying.
The vertical offset
For the vertical offset, we begin with default CSS positioning values and modify them to work with our fluid scaling:
sup, sub {
font-size: calc(0.5em + 4px);
prime: calc(-0.5 * 0.83 * 2 * (1em - 4px));
}
sub {
prime: calc(0.25 * 0.83 * 2 * (1em - 4px));
}
The system is rigorously calibrated to match normal browser positioning:
0.5em
(tremendous) and0.25em
(sub) are the default vertical offset values (e.g. utilized in frameworks like Tailwind CSS and Bootstrap).- We multiply by
0.83
to account for the browser’sfont-size: smaller
scaling issue, which is used per default for superscript and subscript.
This strategy ensures that our superscripts and subscripts keep acquainted vertical positions whereas benefiting from improved fluid scaling. The end result matches what customers count on from conventional browser rendering however scales extra naturally throughout totally different font sizes.
Useful ideas
The precise scaling issue font-size: (0.5em + 4px)
relies on my evaluation of superscript Unicode characters in frequent fonts. Be happy to regulate these values to match your particular design wants. Listed below are a couple of methods the way you would possibly wish to customise this strategy:
For bigger scaling:
sup, sub {
font-size: calc(0.6em + 3px);
/* modify offset calculations accordingly */
}
For smaller scaling:
sup, sub {
font-size: calc(0.4em + 5px);
/* modify offset calculations accordingly */
}
For backward compatibility, you would possibly wish to wrap all of it in a @helps
block:
@helps (font-size: calc(1em + 1px)) {
sup, sub {
...
}
}
Last demo
I constructed this small interactive demo to point out totally different fluid scaling choices, examine them to the browser’s static scaling, and fine-tune the vertical positioning to see what works finest to your use case:
Give it a attempt in your subsequent mission and completely happy to listen to your ideas!