.svelte files using a superset of HTML that combines JavaScript logic, HTML markup, and CSS styles in a single file.
Component structure
A Svelte component consists of up to three sections — all of which are optional:MyComponent.svelte
The <script> block
The <script> block contains JavaScript (or TypeScript with lang="ts") that runs when a component instance is created. Variables declared or imported at the top level are automatically available in the component’s markup.
Basic example
Button.svelte
countis reactive state created with the$stateruneincrementis a function that modifies the state- Both are accessible in the markup below
TypeScript support
Add thelang="ts" attribute to use TypeScript:
Todo.svelte
Reactivity with runes
Svelte’s reactivity system is powered by runes — special function-like constructs that the compiler understands:$state
Creates reactive state that triggers UI updates when changed
$derived
Computes values that automatically update when dependencies change
$effect
Runs side effects when reactive dependencies change
$props
Declares component properties passed from parent components
Calculator.svelte
The <script module> block
A <script> tag with a module attribute runs once when the module first evaluates, rather than for each component instance. This is useful for:
- Shared constants
- Utility functions
- Module-level state shared across all instances
Component.svelte
total increments and is shared across all instances.
Exporting from module blocks
You can export bindings from<script module> blocks, and they become exports of the compiled module:
utils.svelte
Legacy note: In Svelte 4, module scripts used
<script context="module">. Svelte 5 uses the simpler <script module> syntax.Markup
Markup in Svelte components is HTML enhanced with special syntax for:- Template expressions:
{value} - Control flow:
{#if},{#each},{#await} - Event handlers:
onclick={handler} - Bindings:
bind:value={variable} - Directives:
use:action,transition:fade
Example with template features
UserList.svelte
- Two-way binding with
bind:checked - Conditional rendering with
{#if} - List rendering with
{#each} - Class toggling with
class:inactive
The <style> block
CSS inside a <style> block is automatically scoped to the component. Svelte adds unique identifiers to elements and styles, ensuring they don’t leak to other components.
Scoped styles example
Card.svelte
.card, h2, and p only apply to elements within this component instance. Other components can use the same class names and element selectors without conflicts.
Global styles
If you need to apply styles globally, use the:global() modifier:
Complete example
Here’s a complete component that demonstrates all three sections working together:TodoItem.svelte
Key takeaways
- All sections are optional — use only what you need
- Script runs per instance — fresh state for each component
- Script module runs once — shared across all instances
- Styles are scoped — no CSS conflicts between components
- Markup is enhanced HTML — with powerful template features