In the previous lesson, you learned about scoped, component, and global styles in Svelte, which are essential for creating clean and maintainable user interfaces. Now, we’ll take styling a step further by introducing dynamic class binding. This technique allows you to apply or remove CSS classes based on the state of your application, making your components more interactive and visually dynamic.
Dynamic class binding is particularly useful when you want to change the appearance of an element in response to user actions, such as clicking a button or hovering over an element. In Svelte 5, this is achieved using the $state
rune for reactivity and event handlers like onclick
, onmouseenter
, and onmouseleave
. By the end of this lesson, you’ll understand how to use these tools to create components that respond to user interactions with smooth and engaging visual changes.
Let’s start by exploring how to bind a class to a state variable in Svelte. In Svelte 5, reactivity is handled using the $state
rune, which replaces older patterns like stores and $:
. Here’s a simple example where we toggle a class (active
) on a button when it’s clicked:
svelte1<script> 2 let active = $state(false); 3</script> 4 5<button class={["btn", { active }]} onclick={() => active = !active}> 6 Toggle Active State 7</button> 8 9<style> 10 .btn { 11 padding: 10px 20px; 12 border: none; 13 border-radius: 5px; 14 background-color: #ddd; 15 cursor: pointer; 16 } 17 18 .btn.active { 19 background-color: #007bff; 20 color: white; 21 } 22</style>
In this example:
- We define a state variable
active
using$state(false)
, which initializes tofalse
. - The
class
attribute of the button uses an array to combine the static classbtn
with the conditional classactive
. Whenactive
istrue
, theactive
class is applied. - The
onclick
event handler toggles the value ofactive
betweentrue
andfalse
.
When you click the button, it will toggle between the default and active styles, changing the background color to blue and the text color to white.
Sometimes, you’ll want to apply multiple classes conditionally based on different states. For example, you might want to highlight a button when the user hovers over it while also toggling an active state. Here’s how you can achieve this:
svelte1<script> 2 let active = $state(false); 3 let highlighted = $state(false); 4</script> 5 6<button 7 class={["btn", { active, highlighted }]} 8 onclick={() => active = !active} 9 onmouseenter={() => highlighted = true} 10 onmouseleave={() => highlighted = false} 11> 12 Toggle Active State 13</button> 14 15<style> 16 .btn { 17 padding: 10px 20px; 18 border: none; 19 border-radius: 5px; 20 background-color: #ddd; 21 cursor: pointer; 22 } 23 24 .btn.active { 25 background-color: #007bff; 26 color: white; 27 } 28 29 .btn.highlighted { 30 box-shadow: 0 0 8px rgba(0, 123, 255, 0.5); 31 } 32</style>
In this example:
- We introduce a second state variable
highlighted
to track whether the button is being hovered over. - The
class
attribute now includes bothactive
andhighlighted
classes, which are applied conditionally based on their respective state variables. - The
onmouseenter
andonmouseleave
event handlers update thehighlighted
state when the user hovers over or leaves the button.
When you hover over the button, it will gain a subtle box shadow, and clicking it will toggle the active state, changing its background color.
To make your dynamic class changes smoother, you can use CSS transitions. Transitions allow you to animate changes in CSS properties, such as background-color
or box-shadow
, creating a more polished user experience. Here’s how to add transitions to the previous example:
svelte1<style> 2 .btn { 3 padding: 10px 20px; 4 border: none; 5 border-radius: 5px; 6 background-color: #ddd; 7 cursor: pointer; 8 transition: background-color 0.3s ease, box-shadow 0.3s ease; 9 } 10 11 .btn.active { 12 background-color: #007bff; 13 color: white; 14 } 15 16 .btn.highlighted { 17 box-shadow: 0 0 8px rgba(0, 123, 255, 0.5); 18 } 19</style>
In this updated CSS:
- The
transition
property is added to the.btn
class, specifying that changes tobackground-color
andbox-shadow
should animate over 0.3 seconds with an easing effect. - When the
active
orhighlighted
classes are applied or removed, the changes will now animate smoothly instead of happening instantly.
Let’s break down the provided solution.svelte
code to see how all these concepts come together:
svelte1<script> 2 let active = $state(false); 3 let highlighted = $state(false); 4</script> 5 6<button 7 class={["btn", { active }, {highlighted}]} 8 onclick={() => active = !active} 9 onmouseenter={() => highlighted = true} 10 onmouseleave={() => highlighted = false} 11> 12 Toggle Active State 13</button> 14 15<style> 16 .btn { 17 padding: 10px 20px; 18 border: none; 19 border-radius: 5px; 20 background-color: #ddd; 21 cursor: pointer; 22 transition: background-color 0.3s ease; 23 } 24 25 .btn.active { 26 background-color: #007bff; 27 color: white; 28 } 29 30 .btn.highlighted { 31 box-shadow: 0 0 8px rgba(0, 123, 255, 0.5); 32 } 33</style>
In this example:
- The
active
andhighlighted
states are managed using$state
. - The
class
attribute combines the staticbtn
class with the conditionalactive
andhighlighted
classes. - Event handlers (
onclick
,onmouseenter
,onmouseleave
) update the state variables based on user interactions. - CSS transitions ensure that changes to
background-color
andbox-shadow
are smooth and visually appealing.
In most cases, the object shorthand syntax works well for dynamic class binding. However, there are situations where the state variable name does not match the class name, making the shorthand approach less effective.
Let’s say we have a button with two states:
isActive
→ Should apply the"active"
class whentrue
.isDisabled
→ Should apply the"disabled"
class whentrue
.
Since our state names don’t match the class names exactly, using { isActive, isDisabled }
won’t work. Instead, we use JavaScript expressions to manually assign the correct class names.
svelte1<script> 2 let isActive = $state(false); 3 let isDisabled = $state(false); 4</script> 5 6<button 7 class={`btn ${isActive ? 'active' : ''} ${isDisabled ? 'disabled' : ''}`} 8 onclick={() => isActive = !isActive} 9 oncontextmenu={(e) => { e.preventDefault(); isDisabled = !isDisabled; }} 10> 11 Right-click to Disable, Click to Activate 12</button> 13 14<style> 15 .btn { 16 padding: 10px 20px; 17 border: none; 18 border-radius: 5px; 19 background-color: #ddd; 20 cursor: pointer; 21 } 22 23 .btn.active { 24 background-color: #007bff; 25 color: white; 26 } 27 28 .btn.disabled { 29 background-color: #aaa; 30 color: #666; 31 cursor: not-allowed; 32 } 33</style> 34 35If we used `{ isActive, isDisabled }`, Svelte would attempt to apply `isActive` and `isDisabled` as class names, which do not exist in the CSS. By using template literals, we can explicitly map our state variables to the correct class names, ensuring that only valid CSS classes are applied. This method is particularly useful when handling multiple state variables that affect different styles while keeping the class binding logic flexible and maintainable. 36
In this lesson, you learned how to use dynamic class binding in Svelte to create interactive and visually dynamic components. Here’s a quick recap of the key concepts:
- Dynamic Class Binding: Use
$state
to manage state variables and conditionally apply classes based on their values. - Multiple Classes: Combine multiple classes conditionally using the object syntax in the
class
attribute. - CSS Transitions: Add smooth animations to class changes using the
transition
property in CSS. - Event Handling: Use event handlers like
onclick
,onmouseenter
, andonmouseleave
to update state variables in response to user interactions.
In the practice exercises, you’ll apply these concepts to create components that respond to user actions with dynamic styling. Remember, Svelte 5 is pre-installed on CodeSignal, so you can focus on coding without worrying about setup. Experiment with the examples and explore how dynamic class binding can enhance your user interfaces. Great job completing this lesson—you’re one step closer to mastering styling and transitions in Svelte!