Skip to content

Styles

React has no built-in CSS scoping — you choose between CSS Modules, Styled Components, Tailwind, or plain global CSS. Svelte’s <style> block is automatically scoped to the component: every selector gets a unique attribute injected at build time, so .button in one component never clashes with .button in another. No configuration required.

React (CSS Modules)
// Button.module.css
.button { background: #FF3E00; color: white; padding: 0.5rem 1rem; }
// Button.jsx
import styles from './Button.module.css';
function Button({ label }) {
return <button className={styles.button}>{label}</button>;
}
Svelte
<!-- Button.svelte -->
<script>
let { label } = $props();
</script>
<button>{label}</button>
<style>
/* This .button only applies inside this component */
button { background: #FF3E00; color: white; padding: 0.5rem 1rem; }
</style>

Svelte compiles the <style> block and adds a unique hashed attribute to every element touched by it (e.g., <button class="svelte-xyz123">). The selector becomes button.svelte-xyz123 — globally unique, no collision possible.

React developers typically toggle classes with a ternary or a library like clsx. Svelte has a first-class class: directive:

React
function Alert({ message, type = 'info' }) {
return (
<div className={`alert alert--${type}`}>
{message}
</div>
);
}
// With boolean toggle:
<div className={isActive ? 'box box--active' : 'box'}>
Svelte
<script>
let { message, type = 'info' } = $props();
let isActive = $state(false);
</script>
<div class="alert alert--{type}">{message}</div>
<!-- Boolean class toggle — no clsx needed: -->
<div class="box" class:box--active={isActive}>...</div>

class:name={condition} adds name to the element’s class list when condition is truthy, and removes it otherwise. Clean, readable, no string concatenation.

Sometimes you need to target child elements or apply truly global styles. Use :global():

<style>
/* Scoped — only affects elements in this component */
.container { padding: 1rem; }
/* Global — applies everywhere */
:global(body) { margin: 0; }
/* Scoped parent, global child */
.container :global(a) { color: #FF3E00; }
</style>
What happens to CSS selectors inside a Svelte <style> block?
How do you conditionally add a CSS class in Svelte without string concatenation?
How do you write a truly global CSS rule inside a Svelte <style> block?
What is the recommended approach for dynamic theming in Svelte when scoped styles cannot reference runtime JS?