How to dynamically apply CSS in Svelte
By Flavio Copes
Learn how to dynamically apply CSS in Svelte by toggling a class based on a variable, using the class:name directive and its concise shorthand syntax.
To dynamically apply CSS in Svelte, you toggle a class on the element with the class: directive, and write the CSS for that class in the component’s <style> block.
Let me show you how I got there.
I had the need to dynamically apply some CSS properties to an element, using Svelte, when one of its variables had a particular value.
The first solution I found was to add an HTML class when the selected variable value was true, and then I wrote some CSS that targeted that element with the class:
<style>
/* ...other CSS... */
span.cell.selected {
outline-color: lightblue;
outline-style: dotted;
}
</style>
<span class="cell {selected === true ? 'selected' : ''}">
{value}
</span>
This works, but the ternary inside the attribute is noisy. It also leaves a stray space in the class value when selected is false, and it gets messy as soon as you need two or three conditional classes on the same element.
The class: directive
This kind of need is so common that Svelte added the ability to bind the class name to a variable value:
<span class="cell" class:selected="{selected}">
{value}
</span>
Svelte adds the selected class when the variable is truthy, and removes it when it’s falsy. No ternary, no stray spaces.
And in a more concise way, using the shorthand notation:
<span class="cell" class:selected>
{value}
</span>
The shorthand only works when the variable has the same name as the class. class:selected means “add the selected class when the selected variable is truthy”. If your variable is called isActive and your class is called selected, you need the full form: class:selected={isActive}.
Any expression works
You can pass any JavaScript expression, not only a boolean variable:
<span class="cell" class:highlighted={value > 100}>
{value}
</span>
You can also repeat the directive to toggle multiple classes independently:
<span class="cell" class:selected class:highlighted={value > 100}>
{value}
</span>
Each class gets its own condition, and the markup stays readable.
In Svelte 5
The class: directive still works in Svelte 5. What changes is how you declare the variable. With runes, a plain let doesn’t update the page when it changes, so you declare selected with $state:
<script>
let value = 120
let selected = $state(false)
</script>
<button onclick={() => (selected = !selected)}>Select</button>
<span class="cell" class:selected>
{value}
</span>
Click the button and the selected class goes on and off.
The earlier examples in this post still work in Svelte 5 too. A component that doesn’t use any rune runs in legacy mode, and there a plain let is reactive like in Svelte 4.
Since Svelte 5.16, the class attribute also accepts an object. Each key is a class name, and its value decides if the class is applied:
<span class={{ cell: true, selected, highlighted: value > 100 }}>
{value}
</span>
The Svelte docs now suggest avoiding class: unless you’re on an older version of Svelte, because the attribute is more powerful and composable. Both work, so pick the one you find easier to read.
The CSS lives in the component’s <style> block, so Svelte scopes it to the component. Your .selected rule can’t leak out and accidentally style a .selected element somewhere else in the app.
Want me to talk about your product? You can sponsor this site.