Root Cause
So, recently I came across a problem loading web components into a site that utilises the "62.5% sizing' hack. I remember seeing it in a post before thinking it was a nifty approach but not something I'd use in production, and I forgot all about it. Silly me, it turns out some believe that this is a good idea. So what's going on here?
Playing with numbers
The nice thing, and why it's so appealing, is that you can simplify the application of values in an easy-to-read way.
First, you set your root font size to 62.5% of the browser's default font size.
html {
font-size: 62.5%; /* 62.5% of 16px equals 10px */
}
You then need to reset the body's font size that you will use in your document.
body {
font-size: 1.6rem; /* 1.6rem equals 16px */
}
So why do this? Well, now you can do this:
h1 {
font-size: 4.8rem; /* equals 48px */
}
blockquote {
margin-block: 2rem; /* equals 20px */
}
This is a very charming way to make your property values more readable. You are now 10px-based or 5px-based, so if that is not something you're into, this solution quickly becomes more effort than it's worth. Many view the 4px-base as a more natural fit for the web. It is still very readable and easy to work with without changing the default root font size. The reality is that you should use what works for what you're making and resist getting lured into implementation-based solutions. It's the developers' job to make the chosen base size work.
The disconnect
This solution works reasonably well as long as browsers don't change the default font size. I don't see that happening anytime soon. So for a single, stand-alone project, this is workable, but be aware of some caveats.
The thing about changing a root unit size is that it touches elements that use the rem unit. And rem
units have become very popular.
In fact, the root element has become the pattern to set the document's font size. If you set the root element's font size, you don't need to set the font size of the body element.
This 'default by convention' has also allowed the developer to set margins and padding with rem
. There are strategies to mix the various units for better typographical alignment.
/* based on the root font-size being 100% (16px) */
.card {
gap: 2ch;
margin-block: 1rem;
padding: 1em;
}
.card--small {
font-size: 0.875rem;
}
.card h3 {
margin-block: 0.75em 0.5em;
font-size: 1.25rem;
}
The 62.5% sizing approach does require all subsequent rem
units to follow suit. It becomes its own pattern with one side effect that I'm pretty sure was unintentional. Third-party styles and themes can't rely on the root font size being equal to the one used in the document, as a theme may be placed in sites that do have their root sized in relation to the document. They now must explicitly set their sizing values in absolute terms. The relative unit is effectively unusable when a theme needs to be agnostic. Which is often the main requirement of a theme.
I mostly create white-label component libraries that are utilised in a design system. I now must decide whether I should support the 62.5% sizing approach. Where I have the choice, I would not support it because setting the root size like that conceptually breaks the relation (i.e., the cascade) to the font size in the document. This disconnect, to me, is an antipattern.
Custom solution
Dealing with scales and fractions can make a system hard to use and awkward to adopt. But we don't need to fiddle with the root font size to solve this problem. Custom properties can abstract away esoteric fractions and calc()
functions.
html {
font-size: var(--fs-root, 100%);
}
body {
font-size: var(--fs-doc, 1rem);
}
.card {
gap: var(--gap, var(--spacer-small));
margin-block: var(--spacer-base);
padding: var(--spacer-base);
}
.card--large {
font-size: var(--fs-large);
}
.card--small {
font-size: var(--fs-small);
}
I see custom properties being used everywhere. Using these as a natural language to express sizing is a better way to create a consistent and usable scale that doesn't interfere with the cascade.
With custom properties in mind, I no longer see a need to hijack the root. I sincerely hope we don't end up with a situation that requires style queries to deal with unpredictable root sizing. Fixing something that wasn't broken seems so wasteful.