Quick tip: style prop defaults

— 4 minute read

Svelte has a built-in solution for component theming using style props. So, you can use CSS custom properties in your component styles...

<p>
I have something important to say.
</p>

<style>
p {
border: 2px solid var(--line-color);

/* Decorative styles */
padding: 1rem;
max-width: 60ch;
}

</style>

...and easily set them from outside the component using style props.

<TextBox --line-color="mediumspringgreen"></TextBox>

But what if you want your style to have a default value? The custom property var syntax takes a second argument that sets a fallback if the property is not defined. So, if you wanted the default border color to be darkred, you could do the following.

p {
border: 2px solid var(--line-color, darkred);
}

However, this can get verbose if you want to use --line-color in multiple places, with the same fallback. If you want to update the default value, you have to do it multiple places!

p {
border: 2px solid var(--line-color, darkred);
text-decoration: underline wavy var(--line-color, darkred) 1px;
}

There’s two ways to refactor this to make it less verbose. First, you could introduce another custom property for the default value:

p {
--line-color-default: darkred;
border: 2px solid var(--line-color, var(--line-color-default));
text-decoration: underline wavy var(--line-color, var(--line-color-default)) 1px;
}

This makes it so there’s one place to change the default value, but you still have to provide the second argument to var every time you reference --line-color.

Instead, my recommended approach would be to introduce another custom property that represents either line-color or the fallback.

p {
--_line-color: var(--line-color, darkred);

border: 2px solid var(--_line-color);
text-decoration: underline wavy var(--_line-color) 1px;
}

So now you have two variables:

  • --line-color is the user-supplied theme value
  • --_line-color is what we use in our styles, and will either be the user-supplied value (if defined) or the default color

You can see this in action in this Svelte REPL.

You only need to introduce a variable like --_line-color if you plan on using the theme variable multiple places. Otherwise, it’s perfectly fine to set the fallback where you use the property, as in the first example.

The technique on display here is not unique to Svelte, and can be applied anywhere you use custom properties. However, it's of particular interest with Svelte, since custom properties are the recommended way of theming a component.

Want to find out when I post a new article? Follow me on Mastodon or Bluesky or subscribe to my RSS feed. I also have an email newsletter that I'll send out when I post something new, along with anything else I find interesting.

Previous Blog Post: Talking Svelte and open source on 20minJS

Next Blog Post: Svelte Radio Episode 43: The other Rich! Geoff!

twitter.com www.reddit.com