Basic Svelte
Introduction
Bindings
Classes and styles
Advanced Svelte
Advanced reactivity
Motion
Advanced bindings
Advanced transitions
Context API
Special elements
<script module>
Next steps
Basic SvelteKit
Introduction
Routing
Loading data
Headers and cookies
Shared modules
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion
Like any other attribute, you can specify classes with a JavaScript attribute. Here, we could add a flipped
class to the card:
<button
class="card {flipped ? 'flipped' : ''}"
onclick={() => flipped = !flipped}
>
This works as expected — if you click on the card now, it’ll flip.
We can make it nicer though. Adding or removing a class based on some condition is such a common pattern in UI development that Svelte allows you to pass an object or array that is converted to a string by clsx.
<button
class={["card", { flipped }]}
onclick={() => flipped = !flipped}
>
This means ‘always add the card
class, and add the flipped
class whenever flipped
is truthy’.
Note: When using multiple expressions inside a
class={}
attribute, make sure to combine them within a single array or object. Avoid separating expressions with commas at the top level (for example:class={['foo'], 'bar'}
), as this creates a JavaScript sequence expression, which can cause errors in Runes mode and result in unintended behavior.✅ Correct:
<div class={["foo", condition && "bar", "baz"]}></div>
❌ Avoid:
<div class={["foo"], "bar"}></div>
For more examples of how to combine conditional classes, consult the class
documentation.
<script>
let flipped = $state(false);
</script>
<div class="container">
Flip the card
<button
class="card"
onclick={() => flipped = !flipped}
>
<div class="front">
<span class="symbol">♠</span>
</div>
<div class="back">
<div class="pattern"></div>
</div>
</button>
</div>
<style>
.container {
display: flex;
flex-direction: column;
gap: 1em;
height: 100%;
align-items: center;
justify-content: center;
perspective: 100vh;
}
.card {
position: relative;
aspect-ratio: 2.5 / 3.5;
font-size: min(1vh, 0.25rem);
height: 80em;
background: var(--bg-1);
border-radius: 2em;
transform: rotateY(180deg);
transition: transform 0.4s;
transform-style: preserve-3d;
padding: 0;
user-select: none;
cursor: pointer;
}
.card.flipped {
transform: rotateY(0);
}
.front, .back {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
backface-visibility: hidden;
border-radius: 2em;
border: 1px solid var(--fg-2);
box-sizing: border-box;
padding: 2em;
}
.front {
background: url(./svelte-logo.svg) no-repeat 5em 5em, url(./svelte-logo.svg) no-repeat calc(100% - 5em) calc(100% - 5em);
background-size: 8em 8em, 8em 8em;
}
.back {
transform: rotateY(180deg);
}
.symbol {
font-size: 30em;
color: var(--fg-1);
}
.pattern {
width: 100%;
height: 100%;
background-color: var(--bg-2);
/* pattern from https://projects.verou.me/css3patterns/#marrakesh */
background-image:
radial-gradient(var(--bg-3) 0.9em, transparent 1em),
repeating-radial-gradient(var(--bg-3) 0, var(--bg-3) 0.4em, transparent 0.5em, transparent 2em, var(--bg-3) 2.1em, var(--bg-3) 2.5em, transparent 2.6em, transparent 5em);
background-size: 3em 3em, 9em 9em;
background-position: 0 0;
border-radius: 1em;
}
</style>