In this post we will see how you can add Svelte Capsize styling to your SvelteKit app. Although we use SvelteKit you should be able easily to adapt the code for Astro or Slinkity. Before that though we should take a look at what Capsize is and the problems it solves. Capsize is a tool which helps you to design text layouts in a predictable way. Typically to adjust how big a piece of text appears in the browser window, we change the CSS font-size property. This works but the spacing above and below the text as it appears in the browser is not easy to determine. The space below the baseline and above the text is unpredictable and changes from font to font even with fixed font size.
In summary, if you set a font size of
16px or even
1em, you will not know predictably what the height of any displayed character will be. This is
quite different to, for example, how
img or other block elements are
defined — we can reliably and predictably set height for these. Capsize lets us define a cap height to adjust the size of rendered characters. Further, it gives us parameters needed to trim a snug bounding box. This is fantastic for creating predictable text layouts.
In the image above we can see Capsize makes it possible to generate snug text elements. Capsize does this by generating a styles object similar to those created by CSS in JS frameworks. To sveltify these styles objects, we will use Svelte actions and custom properties. Interested to hear if you have another method of attack! Drop a comment below if you do.
Rather than build out an app, in this post we will look at how to set up Capsize and then see a
way to apply the generated styles in Svelte. Although we won’t build out an app, there is a full demo on the Rodney Lab GitHub page
The only setup for Capsize
To get a better understanding of Capsize inputs and outputs, here is a screenshot from a tool on the Capsize site. It shows metrics for the Courier New font which we use in the demo code.
The Em square is a fundamental unit which originates from printing. It is a square with sides set equal to the width of an uppercase ‘M’ printed using the typeface. For us, it represents the space the element takes up on screen and is used to set font size.
We can specify font size or cap height as a Capsize input. Lets say we need tighter
control over the height of each row in our comparison chart (above). Setting cap height gives us the
control and predictability we a looking for; if we want capital letters to be
48px high, we can easily have that by setting cap height to that value. If we were replicating a figma
or penpot design with font heights set we might instead opt for setting font size.
Let’s start by seeing what Capsize creates for us. The second row of the With Capsize /
Wihtout Capsize comparison charts has cap height set to
We’ll use that as a concrete value to examine Capsize inputs and outputs. Since the metrics
vary from font to font, we need to specify our font as an input. Here’s the Svelte code for
48px cap height example:
We import Courier Prime font metrics from
@capsizecss/metrics/courierPrime in line
3. These are then used to generate the styles
Let’s take a peek at these metrics:
These match the data from the screenshot of the tool on the Capsize size above.
The first question you will ask is probably how these numbers relate to the font size. For our
precise use case we want to set cap height so we know how high our upper case letters in the chart
will be. The
unitsPerEm field in the metrics is just the height of
the em square. So the ratio of em square height to cap height is
2048 / 1187 = 1.725. This means if we set capHeight to
48px when using Capsize, we want
48px * 1.725 = 82.8px font for the without Capsize comparison.
You can examine the precise font measurements using FontForge.
It also provides another route to the metrics above.
We won’t go into more detail on metrics here, though there is an excellent Deep dive on font metrics by Vincent De Oliveira
In the rest of the article we focus on the Svelte implementation.
The styles object generated for our example looks like this:
You will notice we have
::after pseudo elements in there. Svelte has style directives (we will see an example shortly) which can
set styles for an element itself, but not for pseudo elements. Using Svelte actions, it is possible
to set custom CSS properties (often also called CSS variables). Our plan of attack is to use Svelte
actions to define all the CSS values we need (pseudo and actual element). We will define these on a
parent wrapper element, so that they are in scope on the actual lines we want to use them in. So markup
is roughly something like this:
with scoped CSS
Svelte lets you define CSS custom properties on an element
That is what we will use Svelte actions for. Svelte actions have the node they are applied to as the first parameter. There can also be a second parameter which takes the value we set on the node. We will use that to pass the styles object in. Then the action’s job is to split the styles object up into custom properties we want added to the node. Here is the code:
The structure of the app is that we create each of the two charts using a Chart Svelte component. Then each line in a chart is a line Svelte component. The line components are where we use Capsize. Here is a possible implementation of the line component, using the new action:
You see how we use the action in code in line
As an aside the two charts have different background colours. In the code where we consume them, we can set the CSS custom property for the background right on the element:
Then in the chart component itself, we use this in the CSS
These are called style props. You can read more on style props in the Svelte docs
For completeness, here is the final Line component code:
src/lib/components/Line.svelte — click to expand code.
The promised style directive example comes in line 29. We set
font-size on the div. We use a style directive here because we have a dynamic property. This value overrides
the one set in the
In this post we looked at:
- how to use Capsize with Svelte for more predictable text layouts,
- adding CSS custom properties to a Svelte element using Svelte actions,
- how you can add style props to Svelte components, setting CSS custom properties (CSS variables).
I do hope there is at least one thing in this article which you can use in your work or a side project. Also let me know if you feel more explanation of the config is needed.
You can see the full SvelteKit code for this project on the Rodney Lab Git Hub repo
- Capsize gives you more control over text layouts. It exists because the way font sizes are defined can make it difficult to determine the height of a text block in the browser. Capsize lets you set the cap height, for more predictable text layouts, especially across different fonts. On top, it calculates CSS adjustments to create a tighter element for your text, making your text layout more predictable.
If you have found this video useful, see links below for further related content on this site. I do hope you learned one new thing from the video. Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on Twitter, giving me a mention so I can see what you did. Finally be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please consider supporting me through Buy me a Coffee.
Just dropped a post talking about using Capsize with ❤️ Svelte.— Rodney (@askRodney) April 29, 2022
You see how to add CSS custom properties (CSS variables) on components and elements in Svelte and also how you can style pseudo-elements with Svelte actions.
Hope you find it useful!
Finally, feel free to share the post on your social media accounts for all your followers who will
find it useful. As well as leaving a comment below, you can get in touch via @askRodney