` elements, or making
network requests. They only run in the browser, not during server-side
rendering.
Generally speaking, you should _not_ update state inside effects, as it will
make code more convoluted and will often lead to never-ending update cycles.
If you find yourself doing so, see when not to use `$effect` to learn about
alternative approaches.
You can create an effect with the `$effect` rune
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE31S246bMBD9lZF3pSRSAqTVvrCAVPUP2sdSKY4ZwJJjkD0hSVH-
vbINuWxXfQH5zMyZc2ZmZLVUaFn6a2R06ZGlHmBrpvnBvb71fWQHVOSwPbf4GS46TajJspRlVhjZU1HqkhQSWPkHIYdXS5xw-
Zas3ueI6FRn7qHFS11_xSRZhIxbFtcDtw7SJb1iXaOg5XIFeQGjzyPRaevYNOGZIJ8qogbpe8CWiy_VzEpTXiQUcvPDkSVrSNZz1UlW1N5eLcqmpdXUvaQ4BmqlhZNUCgxuzFHDqUWNAxrYeUM76AzsnOsdiJbrBp_71lKpn3RRbii-4P3f-IMsRxS-
wcDV_bL4PmSdBa2wl7pKnbp8DMgVvJm8ZNskKRkEM_OzyOKQFkgqOYBQ3Nq89Ns0nbIl81vMFN-
jKoLMTOr-SOBOJS-Z8f5Y6D1wdcR8dFqvEBdetK-PHwj-z-
cH8oHPY54wRJ8Ys7iSQ3Bg3VA9azQbmC9k35kKzYa6PoVtfwbbKVnBixBiGn7Pq0rqJoUtHiCZwAM3jdTPWCVtr_glhVrhecIa3vuksJ_b7TqFs4DPyriSjd5IwoNNQaAmNI-
ESfR2p8zimzvN1swdCkvJHPH6-_oX8o1SgcIDAAA=)):
When Svelte runs an effect function, it tracks which pieces of state (and
derived state) are accessed (unless accessed inside
[`untrack`](svelte#untrack)), and re-runs the function when that state later
changes.
> If you’re having difficulty understanding why your `$effect` is rerunning or
> is not running see understanding dependencies. Effects are triggered
> differently than the `$:` blocks you may be used to if coming from Svelte 4.
### Understanding lifecycle
Your effects run after the component has been mounted to the DOM, and in a
[microtask](https://developer.mozilla.org/en-
US/docs/Web/API/HTML_DOM_API/Microtask_guide) after state changes. Re-runs are
batched (i.e. changing `color` and `size` in the same moment won’t cause two
separate runs), and happen after any DOM updates have been applied.
You can use `$effect` anywhere, not just at the top level of a component, as
long as it is called while a parent effect is running.
> Svelte uses effects internally to represent logic and expressions in your
> template — this is how `hello {name}! ` updates when `name` changes.
An effect can return a _teardown function_ which will run immediately before
the effect re-runs
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE42SQVODMBCF_8pOxkPRKq3HCsx49K4n64xpskjGkDDJ0tph-O8uINo6HjxB3u7HvrehE07WKDbiyZEhi1osRWksRrF57gQdm6E2CKx_dd43zU3co6VB28mIf-
nKO0JH_BmRRRVMQ8XWbXkAgfKtI8jhIpIkXKySu7lSG2tNRGZ1_GlYr1ZTD3ddYFmiosUigbyAbpC2lKbwWJkIB8ZhhxBQBWRSw6FCh3sM8GrYTthL-
wqqku4N44TyqEgwF3lmRHr4Op0PGXoH31c5rO8mqV-
eOZ49bikgtcHBL55tmhIkEMqg_cFB2TpFxjtg703we6NRL8HQFCS07oSUCZi6Rm04lz1yytIHBKoQpo1w6Gsm4gmyS8b8Y5PydeMdX8gwS2Ok4I-ov5NZtvQde95GMsccn_1wzNKfu3RZtS66cSl9lvL7qO1aIk7knbJGvefdtIOzi73M4bYvovUHDFk6AcX_0HRESxnpBOW_jfCDxIZCi_1L_wm4xGQ60wIAAA==)).
{count}
(milliseconds *= 2)}>slower
(milliseconds /= 2)}>faster
Teardown functions also run when the effect is destroyed, which happens when
its parent is destroyed (for example, a component is unmounted) or the parent
effect re-runs.
### Understanding dependencies
`$effect` automatically picks up any reactive values (`$state`, `$derived`,
`$props`) that are _synchronously_ read inside its function body (including
indirectly, via function calls) and registers them as dependencies. When those
dependencies change, the `$effect` schedules a re-run.
If `$state` and `$derived` are used directly inside the `$effect` (for
example, during creation of a [reactive class]($state#Classes)), those values
will _not_ be treated as dependencies.
Values that are read _asynchronously_ — after an `await` or inside a
`setTimeout`, for example — will not be tracked. Here, the canvas will be
repainted when `color` changes, but not when `size` changes
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE31T246bMBD9lZF3pWSlBEirfaEQqdo_2PatVIpjBrDkGGQPJGnEv1e2IZfVal-
wfHzmzJyZ4cIqqdCy9M-F0blDlnqArZjmB3f72XWRHVCRw_bc4me4aDWhJstSlllhZEfbQhekkMDKfwg5PFvihMvX5OXH_CJa1Zrb0-Kpqr5jkiwC48rieuDWQbqgZ6wqFLRcvkC-
hYvnkWi1dWqa8ESQTxFRjfQWsOXiWzmr0sSLhEJu3p1YsoJkNUcdZUnN9dagrBu6FVRQHAM10sJRKgUG16bXcGxQ44AGdt7SDkTDdY02iqLHnJVU6hedlWuIp94JW6Tf8oBt_8GdTxlF0b4n0C35ZLBzXb3mmYn3ae6cOW74zj0YVzDNYXRHFt9mprNgHfZSl6mzml8CMoLvTV6wTZIUDEJv5us2iwMtiJRyAKG4tXnhl8O0yhbML0Wm-B7VNlSSSd31BG7z8oIZZ6dgIffAVY_5xdU9Qrz1Bnx8fCfwtZ7v8Qc9j3nB8PqgmMWlHIID6-bkVaPZwDySfWtKNGtquxQ23Qlsq2QJT0KIqb8dL0up6xQ2eIBkAg_c1FI_YqW0neLnFCqFpwmreedJYT7XX8FVOBfwWRhXstZrSXiwKQjUhOZeMIleb5JZfHWn2Yq5pWEpmR7Hv-
N_wEqT8hEEAAA=)):
$effect(() => {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// this will re-run whenever `color` changes...
context.fillStyle = color;
setTimeout(() => {
// ...but not when `size` changes
context.fillRect(0, 0, size, size);
}, 0);
});
An effect only reruns when the object it reads changes, not when a property
inside it changes. (If you want to observe changes _inside_ an object at dev
time, you can use [`$inspect`]($inspect).)
(state.value += 1)}>
{state.value}
{state.value} doubled is {derived.value}
An effect only depends on the values that it read the last time it ran. This
has interesting implications for effects that have conditional code.
For instance, if `condition` is `true` in the code snippet below, the code
inside the `if` block will run and `color` will be evaluated. As such, changes
to either `condition` or `color` [will cause the effect to re-
run](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE21RQW6DMBD8ytaNBJHaJFLViwNIVZ8RcnBgXVk1xsILTYT4e20TQg89IOPZ2fHM7siMaJBx9tmaWpFqjQNlAKXEihx7YVJpdIyfRkY3G4gB8Pi97cPanRtQU8AuwuF_eNUaQuPlOMtc1SlLRWlKUo1tOwJflUikQHZtA0klzCDc64Imx0ANn8bInV1CDhtHgjClrsftcSXotluLybOUb3g4JJHhOZs5WZpuIS9gjNqkJKQP5e2ClrR4SMdZ13E4xZ8zTPOTJU2A2uE_PQ9COCI926_hTVarIU4hu_REPlBrKq2q73ycrf1N-vS4TMUsulaVg3EtR8H9rFgsg8uUsT1B2F9eshigZHBRpuaD0D3mY8Qm2BfB5N2YyRzdNEYVDy0Ja-
WsFjcOUuP1HvFLWA6H3XuHTUSmmDV2--0TXonxsKbp7G9C6R__NONS-MFNvxj_d6mBAgAA).
Conversely, if `condition` is `false`, `color` will not be evaluated, and the
effect will _only_ re-run again when `condition` changes.
import confetti from 'canvas-confetti';
let condition = $state(true);
let color = $state('#ff3e00');
$effect(() => {
if (condition) {
confetti({ colors: [color] });
} else {
confetti();
}
});
## $effect.pre
In rare cases, you may need to run code _before_ the DOM updates. For this we
can use the `$effect.pre` rune:
{#each messages as message}
{message}
{/each}
Apart from the timing, `$effect.pre` works exactly like `$effect`.
## $effect.tracking
The `$effect.tracking` rune is an advanced feature that tells you whether or
not the code is running inside a tracking context, such as an effect or inside
your template
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAACn3PwYrCMBDG8VeZDYIt2PYeY8Dn2HrIhqkU08nQjItS-u6buAt7UDzmz8ePyaKGMWBS-
nNRcmdU-
hHUTpGbyuvI3KZvDFLal0v4qvtIgiSZUSb5eWSxPfWSc4oB2xDP1XYk8HHiSHkICeXKeruDDQ4Demlldv4y0rmq6z10HQwuJMxGVv4mVVXDwcJS0jP9u3knynwtoKz1vifT_Z9Jhm0WBCcOTlDD8kyspmML5qNpHg40jc3fFryJ0iWsp_UHgz3180oBAAA=)):
in template: {$effect.tracking()}
It is used to implement abstractions like [`createSubscriber`](svelte-
reactivity#createSubscriber), which will create listeners to update reactive
values but _only_ if those values are being tracked (rather than, for example,
read inside an event handler).
## $effect.root
The `$effect.root` rune is an advanced feature that creates a non-tracked
scope that doesn’t auto-cleanup. This is useful for nested effects that you
want to manually control. This rune also allows for the creation of effects
outside of the component initialisation phase.
const destroy = $effect.root(() => {
$effect(() => {
// setup
});
return () => {
// cleanup
};
});
// later...
destroy();
## When not to use $effect
In general, `$effect` is best considered something of an escape hatch — useful
for things like analytics and direct DOM manipulation — rather than a tool you
should use frequently. In particular, avoid using it to synchronise state.
Instead of this...
...do this:
> For things that are more complicated than a simple expression like `count *
> 2`, you can also use `$derived.by`.
If you’re using an effect because you want to be able to reassign the derived
value (to build an optimistic UI, for example) note that [deriveds can be
directly overridden]($derived#Overriding-derived-values) as of Svelte 5.25.
You might be tempted to do something convoluted with effects to link one value
to another. The following example shows two inputs for “money spent” and
“money left” that are connected to each other. If you update one, the other
should update accordingly. Don’t use effects for this
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE5WRTWrDMBCFryKGLBJoY3fRjWIHeoiu6i6UZBwEY0VE49TB-O6VxrFTSih0qe_Ne_OjHpxpEDS8O7ZMeIAnqC1hAP3RA1990hKI_Fb55v06XJA4sZ0J-IjvT47RcYyBIuzP1vO2chVHHFjxiQ2pUr3k-SZRQlbBx_LIFoEN4zJfzQph_UMQr4hRXmBd456Xy5Uqt6pPKHmkfmzyPAZL2PCnbRpg8qWYu63I7lu4gswOSRYqrPNt3CgeqqzgbNwRK1A76w76YqjFspfcQTWmK3vJHlQm1puSTVSeqdOc_r9GaeCHfUSY26TXry6Br4RSK3C6yMEGT-
aqVU3YbUZ2NF6rfP2KzXgbuYzY46czdgyazy0On_FlLH3F-UDXhgIO35UGlA1rAgAA)):
{spent}/{total} spent
{left}/{total} left
Instead, use `oninput` callbacks or — better still — [function
bindings](bind#Function-bindings) where possible
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE5VRvW7CMBB-
FcvqECQK6dDFJEgsnfoGTQdDLsjSxVjxhYKivHvPBwFUsXS8774_nwftbQva6I_e78gdvNo6Xzu_j3quG4cQtfkaNJ1DIiWA8atkE8IiHgEpYVsb4Rm-O3gCT2yji7jrXKB15StiOJKiA1lUpXrL81VCEUjFwHTGXiJZgiyf3TYIjSxq6NwR6uyifr0ohMbEZnpHH2rWf7ImS8KZGtK6osl_UqelRIyVL5b3ir5AuwWUtoXzoee6fIWy0p31e6i0XMocLfZQDuI6qtaeykGcR7UU6XWznFAZU9LN_X9B2UyVayk9f3ji0-REugen6U9upDOCcAWcLlS7GNCejWoQTqsLtrfBqHzxDu3DrUTOf0xwIm2o62H85sk6_OHG2jQWI4y_3byXXGMCAAA=)):
{spent}/{total} spent
left, updateLeft} max={total} />
{left}/{total} left
If you absolutely have to update `$state` within an effect and run into an
infinite loop because you read and write to the same `$state`, use
[untrack](svelte#untrack).
# $host
### On this page
* [$host]($host)
When compiling a component as a [custom element](custom-elements), the `$host`
rune provides access to the host element, allowing you to (for example)
dispatch custom events
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE41Ry2rDMBD8FSECtqkTt1fHFpSSL-
ix7sFRNkTEXglrnTYY_3uRlDgxTaEHIfYxs7szA9-rBizPPwZOZwM89wmecqxbF70as7InaMjltrWFR3mpkQDJ8pwXVnbKkKiwItUa3RGLVtk7gTHQXRDR2lXda4CY1D0SK9nCUk0QPyfrCovsRoNFe17aQOAwGncgO2gBqRzihJXiQrEs2csYOhQ-7HgKHaLIbpRhhBG-I2eD_8ciM4KnnOCbeE5dD2P6h0Dz0-Yi_arNhPLJXBtSGi2TvSXdbpqwdsXvjuYsC1veabvvUTog2ylrapKH2G2XsMFLS4uDthQnq2t1cwKkGOGLvYU5PvaQxLsxOkPmsm97Io1Mo2yUPF6VnOZFkw1RMoopKLKAE_9gmGxyDFMwMcwN-
Bx_ABXQWmOtAgAA)):
Stepper
dispatch('decrement')}>decrement
dispatch('increment')}>increment
dispatch('decrement')}>decrement
dispatch('increment')}>increment
App
count -= 1}
onincrement={() => count += 1}
>
count: {count}
count -= 1}
onincrement={() => count += 1}
>
count: {count}
# $inspect
### On this page
* [$inspect]($inspect)
* $inspect(...).with
* $inspect.trace(...)
> `$inspect` only works during development. In a production build it becomes a
> noop.
The `$inspect` rune is roughly equivalent to `console.log`, with the exception
that it will re-run whenever its argument changes. `$inspect` tracks reactive
state deeply, meaning that updating something inside an object or array using
fine-grained reactivity will cause it to re-fire
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAACkWQ0YqDQAxFfyUMhSotdZ-
tCvu431AXtGOqQ2NmmMm0LOK_r7Utfby5JzeXTOpiCIPKT5PidkSVq2_n1F7Jn3uIcEMSXHSw0evHpAjaGydVzbUQCmgbWaCETZBWMPlKj29nxBDaHj_edkAiu12JhdkYDg61JGvE_s2nR8gyuBuiJZuDJTyQ7eE-
IEOzog1YD80Lb0APLfdYc5F9qnFxjiKWwbImo6_llKRQVs-2u91c_bD2OCJLkT3JZasw7KLA2XCX31qKWE6vIzNk1fKE0XbmYrBTufiI8-_8D2cUWBA_AQAA)):
count++}>Increment
## $inspect(...).with
`$inspect` returns a property `with`, which you can invoke with a callback,
which will then be invoked instead of `console.log`. The first argument to the
callback is either `"init"` or `"update"`; subsequent arguments are the values
passed to `$inspect`
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAACkVQ24qDMBD9lSEUqlTqPlsj7ON-w7pQG8c2VCchmVSK-
O-bKMs-
DefKYRYx6BG9qL4XQd2EohKf1opC8Nsm4F84MkbsTXAqMbVXTltuWmp5RAZlAjFIOHjuGLOP_BKVqB00eYuKs82Qn2fNjyxLtcWeyUE2sCRry3qATQIpJRyD7WPVMf9TW-7xFu53dBcoSzAOrsqQNyOe2XUKr0Xi5kcMvdDB2wSYO-I9vKazplV1-T-d6ltgNgSG1KjVUy7ZtmdbdjqtzRcphxMS1-XubOITJtPrQWMvKnYB15_1F7KKadA_AQAA)):
count++}>Increment
A convenient way to find the origin of some change is to pass `console.trace`
to `with`:
$inspect(stuff).with(console.trace);
## $inspect.trace(...)
This rune, added in 5.14, causes the surrounding function to be _traced_ in
development. Any time the function re-runs as part of an [effect]($effect) or
a [derived]($derived), information will be printed to the console about which
pieces of reactive state caused the effect to fire.
`$inspect.trace` takes an optional first argument which will be used as the
label.
# $props
### On this page
* [$props]($props)
* Fallback values
* Renaming props
* Rest props
* Updating props
* Type safety
* $props.id()
The inputs to a component are referred to as _props_ , which is short for
_properties_. You pass props to components just like you pass attributes to
elements:
App
On the other side, inside `MyComponent.svelte`, we can receive props with the
`$props` rune...
MyComponent
this component is {props.adjective}
this component is {props.adjective}
...though more commonly, you’ll
[_destructure_](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) your
props:
MyComponent
this component is {adjective}
this component is {adjective}
## Fallback values
Destructuring allows us to declare fallback values, which are used if the
parent component does not set a given prop (or the value is `undefined`):
let { adjective = 'happy' } = $props();
> Fallback values are not turned into reactive state proxies (see Updating
> props for more info)
## Renaming props
We can also use the destructuring assignment to rename props, which is
necessary if they’re invalid identifiers, or a JavaScript keyword like
`super`:
let { super: trouper = 'lights are gonna find me' } = $props();
## Rest props
Finally, we can use a _rest property_ to get, well, the rest of the props:
let { a, b, c, ...others } = $props();
## Updating props
References to a prop inside a component update when the prop itself updates —
when `count` changes in `App.svelte`, it will also change inside
`Child.svelte`. But the child component is able to temporarily override the
prop value, which can be useful for unsaved ephemeral state
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE6WQ0WrDMAxFf0WIQR0Wmu3VTQJln7HsIfVcZubIxlbGRvC_DzuBraN92qPula50tODZWB1RPi_IX16jLALWSOOUq6P3-_ihLWftNEZ9TVeOWBNHlNhGFYznfqCBzeRdYHh6M_YVzsFNsNs3pdpGd4eBcqPVDMrNxNDBXeSRtXioDgO1zU8ataeZ2RE4Utao924RFXQ9iHXwvoPHKpW1xY4g_Bg0cSVhKS0p560Za95612ZC02ONrD8ZJYdZp_rGQ37ff_mSP86Np2TWZaNNmdcH56P4P67K66_SXoK9pG-5dF5Z9QEAAA==)):
App
(count += 1)}>
clicks (parent): {count}
(count += 1)}>
clicks (parent): {count}
Child
(count += 1)}>
clicks (child): {count}
(count += 1)}>
clicks (child): {count}
While you can temporarily _reassign_ props, you should not _mutate_ props
unless they are [bindable]($bindable).
If the prop is a regular object, the mutation will have no effect
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE3WQwU7DMBBEf2W1QmorQgJXk0RC3PkBwiExG9WQrC17U4Es_ztKUkQp9OjxzM7bjcjtSKjwyfKNp1aLORA4b13ADHszUED1HFE-3eyaBcy-
Mw_O5eFAg8xa1wb6T9eWhVgCKiyD9sZJ3XAjZnTWCzzuzfAKvbcjbPJieR2jm_uGy-
InweXqtd0baaliBG0nFgW3kBIUNWYo9CGoxE-
UsgvIpw2_oc9-LmAPJBCPDJCggqvlVtvdH9puErEMlvVg9HsVtzuoaojzkKKAfRuALVDfk5ZZW0fmy05wXcFdwyktlUs-
KIinljTXrRVnm7-kL9dYLVbUAQAA)):
App
Child
{
// has no effect
object.count += 1
}}>
clicks: {object.count}
{
// has no effect
object.count += 1
}}>
clicks: {object.count}
If the prop is a reactive state proxy, however, then mutations _will_ have an
effect but you will see an [`ownership_invalid_mutation`](runtime-
warnings#Client-warnings-ownership_invalid_mutation) warning, because the
component is mutating state that does not ‘belong’ to it
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE3WR0U7DMAxFf8VESBuiauG1WycheOEbKA9p67FA6kSNszJV-
XeUZhMw2GN8r-1znUmQ7FGU4pn2UqsOes-
SlSGRia3S6ET5Mgk-2OiJBZGdOh6szd0eNcdaIx3-V28NMRI7UYq1awdleVNTzaq3ZmB43CndwXYwPSzyYn4dWxermqJRI4Np3rFlqODasWRcTtAaT1zCHYSbVU3r4nsyrdPMKTUFKDYiE4yfLEoePIbsQpqfy3_nOVMuJIqg0wk1RFg7GOuWfwEbz2wIDLVatR_VtLyBagNTHFIUMCqtoZXeIfAOU1JoUJsR2IC3nWTMjt7GM4yKdyBhlAMpesvhydCC0y_i0ZagHByMh26WzUhXUUxKnpbcVnBfUwhznJnNlac7JkuIURL-2VVfwxflyrWcSQIAAA==)):
App
Child
{
// will cause the count below to update,
// but with a warning. Don't mutate
// objects you don't own!
object.count += 1
}}>
clicks: {object.count}
{
// will cause the count below to update,
// but with a warning. Don't mutate
// objects you don't own!
object.count += 1
}}>
clicks: {object.count}
The fallback value of a prop not declared with `$bindable` is left untouched —
it is not turned into a reactive state proxy — meaning mutations will not
cause updates
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE3WQwU7DMBBEf2VkIbUVoYFraCIh7vwA4eC4G9Wta1vxpgJZ_nfkBEQp9OjxzOzTRGHlkUQlXpy9G0gq1idCL43ppDrAD84HUYheGwqieo2CP3y2Z0EU3-En79fhRIaz1slA_-
nKWSbLQVRiE9SgPTetbVkfvRsYzztttugHd8RiXU6vr-
jisbWb8idhN7O3bEQhmN5ZVDyMlIorcOddv_Eufq4AGmJEuG5PilEjQrnRcoV7JCTUuJlGWq7-YHYjs7NwVhmtDnVcrlA3iLmzLLGTAdaB-j736h68Oxv-
JM1I0AFjoG1OzPfX023c1nhobUoT39QeKsRzS8owM8DFTG_pE6dcVl70AQAA))
Child
{
// has no effect if the fallback value is used
object.count += 1
}}>
clicks: {object.count}
{
// has no effect if the fallback value is used
object.count += 1
}}>
clicks: {object.count}
In summary: don’t mutate props. Either use callback props to communicate
changes, or — if parent and child should share the same object — use the
[`$bindable`]($bindable) rune.
## Type safety
You can add type safety to your components by annotating your props, as you
would with any other variable declaration. In TypeScript that might look like
this...
...while in JSDoc you can do this:
You can, of course, separate the type declaration from the annotation:
> Interfaces for native DOM elements are provided in the `svelte/elements`
> module (see [Typing wrapper components](typescript#Typing-wrapper-
> components))
Adding types is recommended, as it ensures that people using your component
can easily discover which props they should provide.
## $props.id()
This rune, added in version 5.20.0, generates an ID that is unique to the
current component instance. When hydrating a server-rendered component, the
value will be consistent between server and client.
This is useful for linking elements via attributes like `for` and `aria-
labelledby`.
# $state
### On this page
* [$state]($state)
* $state.raw
* $state.snapshot
* Passing state into functions
* Passing state across modules
The `$state` rune allows you to create _reactive state_ , which means that
your UI _reacts_ when it changes.
count++}>
clicks: {count}
Unlike other frameworks you may have encountered, there is no API for
interacting with state — `count` is just a number, rather than an object or a
function, and you can update it like you would update any other variable.
### Deep state
If `$state` is used with an array or a simple object, the result is a deeply
reactive _state proxy_. [Proxies](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) allow Svelte to run
code when you read or write properties, including via methods like
`array.push(...)`, triggering granular updates.
State is proxified recursively until Svelte finds something other than an
array or simple object (like a class). In a case like this...
let todos = $state([
{
done: false,
text: 'add more todos'
}
]);
...modifying an individual todo’s property will trigger updates to anything in
your UI that depends on that specific property:
todos[0].done = !todos[0].done;
If you push a new object to the array, it will also be proxified:
todos.push({
done: false,
text: 'eat lunch'
});
> When you update properties of proxies, the original object is _not_ mutated.
Note that if you destructure a reactive value, the references are not reactive
— as in normal JavaScript, they are evaluated at the point of destructuring:
let { done, text } = todos[0];
// this will not affect the value of `done`
todos[0].done = !todos[0].done;
### Classes
Class instances are not proxied. Instead, you can use `$state` in class fields
(whether public or private), or as the first assignment to a property
immediately inside the `constructor`:
class Todo {
done = $state(false);
constructor(text) {
this.text = $state(text);
}
reset() {
this.text = '';
this.done = false;
}
}
> The compiler transforms `done` and `text` into `get` / `set` methods on the
> class prototype referencing private fields. This means the properties are
> not enumerable.
When calling methods in JavaScript, the value of
[`this`](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Operators/this) matters. This won’t work,
because `this` inside the `reset` method will be the `` rather than
the `Todo`:
reset
You can either use an inline function...
todo.reset()}>
reset
...or use an arrow function in the class definition:
class Todo {
done = $state(false);
constructor(text) {
this.text = $state(text);
}
reset = () => {
this.text = '';
this.done = false;
}
}
> Svelte provides reactive implementations of built-in classes like `Set` and
> `Map` that can be imported from [`svelte/reactivity`](svelte-reactivity).
## $state.raw
In cases where you don’t want objects and arrays to be deeply reactive you can
use `$state.raw`.
State declared with `$state.raw` cannot be mutated; it can only be
_reassigned_. In other words, rather than assigning to a property of an
object, or using an array method like `push`, replace the object or array
altogether if you’d like to update it:
let person = $state.raw({
name: 'Heraclitus',
age: 49
});
// this will have no effect
person.age += 1;
// this will work, because we're creating a new person
person = {
name: 'Heraclitus',
age: 50
};
This can improve performance with large arrays and objects that you weren’t
planning to mutate anyway, since it avoids the cost of making them reactive.
Note that raw state can _contain_ reactive state (for example, a raw array of
reactive objects).
As with `$state`, you can declare class fields using `$state.raw`.
## $state.snapshot
To take a static snapshot of a deeply reactive `$state` proxy, use
`$state.snapshot`:
This is handy when you want to pass some state to an external library or API
that doesn’t expect a proxy, such as `structuredClone`.
## Passing state into functions
JavaScript is a _pass-by-value_ language — when you call a function, the
arguments are the _values_ rather than the _variables_. In other words:
index
/**
* @param {number} a
* @param {number} b
*/
function add(a, b) {
return a + b;
}
let a = 1;
let b = 2;
let total = add(a, b);
console.log(total); // 3
a = 3;
b = 4;
console.log(total); // still 3!
function add(a: number, b: number) {
return a + b;
}
let a = 1;
let b = 2;
let total = add(a, b);
console.log(total); // 3
a = 3;
b = 4;
console.log(total); // still 3!
If `add` wanted to have access to the _current_ values of `a` and `b`, and to
return the current `total` value, you would need to use functions instead:
index
/**
* @param {() => number} getA
* @param {() => number} getB
*/
function add(getA, getB) {
return () => getA() + getB();
}
let a = 1;
let b = 2;
let total = add(() => a, () => b);
console.log(total()); // 3
a = 3;
b = 4;
console.log(total()); // 7
function add(getA: () => number, getB: () => number) {
return () => getA() + getB();
}
let a = 1;
let b = 2;
let total = add(() => a, () => b);
console.log(total()); // 3
a = 3;
b = 4;
console.log(total()); // 7
State in Svelte is no different — when you reference something declared with
the `$state` rune...
let a =
namespace $state
namespace $state
Declares reactive state.
Example:
let count = $state(0);
[https://svelte.dev/docs/svelte/$state]($state)
@paraminitial The initial value
$state(1); let `let b: number`b = `
function $state<2>(initial: 2): 2 (+1 overload)
` namespace $state
Declares reactive state.
Example:
let count = $state(0);
[https://svelte.dev/docs/svelte/$state]($state)
@paraminitial The initial value
$state(2);
...you’re accessing its _current value_.
Note that ‘functions’ is broad — it encompasses properties of proxies and
[`get`](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Functions/get)/[`set`](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Functions/set) properties...
index
/**
* @param {{ a: number, b: number }} input
*/
function add(input) {
return {
get value() {
return input.a + input.b;
}
};
}
let input = $state({ a: 1, b: 2 });
let total = add(input);
console.log(total.value); // 3
input.a = 3;
input.b = 4;
console.log(total.value); // 7
function add(input: { a: number, b: number }) {
return {
get value() {
return input.a + input.b;
}
};
}
let input = $state({ a: 1, b: 2 });
let total = add(input);
console.log(total.value); // 3
input.a = 3;
input.b = 4;
console.log(total.value); // 7
...though if you find yourself writing code like that, consider using classes
instead.
## Passing state across modules
You can declare state in `.svelte.js` and `.svelte.ts` files, but you can only
_export_ that state if it’s not directly reassigned. In other words you can’t
do this:
state.svelte
export let count = $state(0);
export function increment() {
count += 1;
}
That’s because every reference to `count` is transformed by the Svelte
compiler — the code above is roughly equivalent to this:
state.svelte
export let count = $.state(0);
export function increment() {
$.set(count, $.get(count) + 1);
}
> You can see the code Svelte generates by clicking the ‘JS Output’ tab in the
> [playground](https://svelte.dev/playground).
Since the compiler only operates on one file at a time, if another file
imports `count` Svelte doesn’t know that it needs to wrap each reference in
`$.get` and `$.set`:
import { count } from './state.svelte.js';
console.log(typeof count); // 'object', not 'number'
This leaves you with two options for sharing state between modules — either
don’t reassign it...
// This is allowed — since we're updating
// `counter.count` rather than `counter`,
// Svelte doesn't wrap it in `$.state`
export const counter = $state({
count: 0
});
export function increment() {
counter.count += 1;
}
...or don’t directly export it:
let count = $state(0);
export function getCount() {
return count;
}
export function increment() {
count += 1;
}
# {@attach ...}
### On this page
* [{@attach ...}](@attach)
* Attachment factories
* Inline attachments
* Passing attachments to components
* Controlling when attachments re-run
* Creating attachments programmatically
* Converting actions to attachments
Attachments are functions that run in an [effect]($effect) when an element is
mounted to the DOM or when [state]($state) read inside the function updates.
Optionally, they can return a function that is called before the attachment
re-runs, or after the element is later removed from the DOM.
> Attachments are available in Svelte 5.29 and newer.
App
...
...
An element can have any number of attachments.
## Attachment factories
A useful pattern is for a function, such as `tooltip` in this example, to
_return_ an attachment
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE3VT0XLaMBD8lavbDiaNCUlbHhTItG_5h5AH2T5ArdBppDOEMv73SkbGJGnH47F9t3un3TsfMyO3mInsh2SW1Sa7zlZKo8_E0zHjg42pGAjxBPxp7cTvUHOMldLjv-
IVGUbDoUw295VTlh-
WZslqa8kxsLL2ACtHWxh175NffnQfAAGikSGxYQGfPEvGfPSIWtOH0TiBVo2pWJEBJtKhQp4YYzjG9JIdcuMM5IZqHMPioY8vOSA997zQoevf4a7heO7cdp34olRiTGr07OhwH1IdoO2A7dLMbwahZq6MbRhKZWqxk7rBxTGVbuHmhCgb5qDgmIx_J6XtHHukHTrYYqx_YpzYng8aO4RYayql7hU-1ZJl0akqHBE_D9KLolwL-
Dibzc7iSln9XjtqTF1UpMkJ2EmXR-
BgQErsN4pxIJKr0RVO1qrxAqaTO4fbc9bKulZm3cfDY3aZDgvFGErWjmzhN7KmfX5rXyDeX8Pt1mU-
hXjdBOrtuB97vK4GPUtmJ41XcRMEGDLD8do0nJ73zhUhSlyRw0t3vPqD8cjfLs-
axiFgNBrkUd9Ulp50c-GLxlXAVlJX-
ffpZyiSn7H0eLCUySZQcQdXlxj4El0Yv_FZvIKElqqGTruVLhzu7VRKCh22_5toOyxsWqLwwzK-
cCbYNdg-hy-p9D7sbiZWUnts_wLUOF3CJgQAAA==)):
App
Hover me
Hover me
Since the `tooltip(content)` expression runs inside an [effect]($effect), the
attachment will be destroyed and recreated whenever `content` changes. The
same thing would happen for any state read _inside_ the attachment function
when it first runs. (If this isn’t what you want, see Controlling when
attachments re-run.)
## Inline attachments
Attachments can also be created inline
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE71Wf3OaWBT9KoyTTnW3MS-I3dYmnWXVtnRAazRJzbozRSQEApiRhwKO333vuY8m225m_9yZGOT9OPfcc84D943UTfxGr_G7K6Xr3TVeNW7D2M8avT_3DVk-
YAoDNF4vNB8e2tnWjyXGlm7mPzfurVPpp5JgGmeZtwkf5PtFupCxLzVvHa832rl2lElX-s2Xm2DZFNqp_hs-
rZetd4v07ORpT3qmQHu7MF2td0BZp8k6z_xkvfXP902_pZ2_1_aYWEiqm0kN8I4r79qbdZ6umnq3q_2iNf22F4dE6qt2oimwdpim_uY6XMm7Fuo-
IQT_iTD_CeGTHwZ38ieIJUFQRxirR1Xf39Dw0X5z0I72Af4tD61vvPNwWKQnqmfPTbduhsEd2J3vO_oBd3dc6fF2X7umNdWGf0vBRhSS6qoV7cCXfTXWfKmvWG61_si_vfU92Wz-E4RhsLhNIYinsox9QKGVd8-tuACCeKXRX12P-T_eKf7fhTq0Hvt-f3ailtSeoxJHRo1-58NoPe1UiBc1hkL8Yeh45y_vQ3mcuNl9T8s3cXPRWLnS7YWJG_gn2Tb4tUjid8jua-
PVl08j_ab8I14mH8Llx0s5Tz5Err4ql52r_GYg0mVy1bEGZuD0ze64b5TWYFiM-16wSuJ4JT5vfVpDcztrcG_YkRU4s6HxufzDWF4XuVeJ1P10IbzBemt3Vp1V2e04ZXfrJd7Wicyd039brRIv_RIVu_nXi7X1cfL2sy66ztToUp1TO7qJ7NlwZ0f30pld5qNSVE5o6PbMojFHjgZB7oSicPpGteyLclQap7SvY0dXtM_LR1NT2JFHey3aaxa0VxCeYJ7RMHemoiCcgPZV9pR7o7kgcOjeGliYk9hjDZx8FAq6enwlTPSZj_vYPw9Il64dXdIY8ZmapzwfEd8-1ZyaxWhqkIZOibXUd-6Upqi1pD4uMicCV1GA_7zi73UN8BaF4sC8peJtMjfmjbHZBFwq5ov50qRaE0l96NZggnW4KqypYRAW-
uhSz9ADvklwJF2J-5W0Z5fQPBhDX92R6I_0IFxRgDftge4l4dP-gH1hjD7uqU6fsOEZ9UNrCdPB-
nys6uXgY6O3ZMd9sy5T9PghqrWHdjo4jB51CgLiKJaDYYA-7WgYONf1FbjkI-
mE3EAfUY_rijfuJ_CVPaR50oe9JF7Q0pI8Dw3osxxYHdYPGbp2CnwHF8KvwJv2wEv0Z3ilQI6U9uwbZxbYJXvEmjjQjjCHkvNLvNg3yhzXQd1olamsT4IRrZmX0MUDpwL7R8zzHj7pSh9hPHFSHjLezKqAST51uC5zmtQ87skDUaneLokT5RbXkPWSYz53Abgjc8_o4KFGUZ-
Hgv2Z1l5OTYM9D-HfUD0L-EwxH5wRnIG61gS-
khfgY1bq7IAP_DA4l5xRuh9xlm8yGjutc8t-wHtkhWv3hc7aqGwiK5KzgvM5xRkZYn193uEln-
su55j1GaIv7oM4iPrsVHiG0Dx7TR9-1lBfqFdwfvSd5LNL5xyZVp5NoHFZ57FkfiF6vKs4k5zvIfrX5xX6MXmt0gM5MTu8DjnhukrHHzTRd3jm0dma0_f_x5cxP9f4jBdqHvmbq2fUjzqcKh2Cp-
yWj9ntcHanXmBXxhu7Q--
eyjhfNFpaV7zgz4nWEUb7zUOhpevjjf_gu_KZ99pxFlZ-T3sttkmYqrco_26q35v0Ewzv5EZPbnL_8BfduWGMnyyN3q0bZ_7hb_7KG_L4CQAA)):
App
{
const context = canvas.getContext('2d');
$effect(() => {
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
});
}}
>
> The nested effect runs whenever `color` changes, while the outer effect
> (where `canvas.getContext(...)` is called) only runs once, since it doesn’t
> read any reactive state.
## Passing attachments to components
When used on a component, `{@attach ...}` will create a prop whose key is a
[`Symbol`](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Symbol). If the component then
[spreads](https://svelte.dev/tutorial/svelte/spread-props) props onto an
element, the element will receive those attachments.
This allows you to create _wrapper components_ that augment elements
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE3VUS3ObMBD-
KxvajnFqsJM2PhA7TXrKob31FjITAbKtRkiMtDhJPfz3LiAMdpxhGJvdb1_fPnaeYjn3Iu-
WIbJ04028lZDcetHDzsO3olbVApI74F1RhHbLJdayhFl-
Sp5qhVwhufEWNjWiwJtYxSjyQhsEFEXxBiujcxg1_8O_dnQ9APwsEbVyiHDafjrvDZCgkiO4MLCEzxYZcn90z6XUZ6OxA61KlaIgV6i1pFC-
sxjDrlbHaDiWRoGvdMbHsLzp5DES0mJnRxGaRBvcBHb7yFUTCQeunEWYcYtGv12TqgFUDbCK1WLaM6IWQhUlQiJUFm2ZLPly51xXMG0Rjoyd69C7UqqG2nu95QZyXvtvLVpri2-SN4hoLXXCZFfhQ8aQBU1VgdEaH_vSgyBZR_BpPp_vi0tY-
rw2ulRZkGqpTQRbZvwa2BPgFC8bgbw31CbjJjAsE6WNYBZeGp7vtQXLMqHWnZx-5kM1TR5ycpkZXQR2wzL94l8Ur1C_3-g168SfQf1MyfRi3LW9fs77emJEw5QV9SREoLTq06tcczq7d6xEUcJX2vAhO1b843XK34e5unZEMBr15ekuKEusluWAF8lXhE2ZTP2r2RcIHJ-163FPKerCgYJLOB9i4GvNwviI5-gAQiFFBk3tBTOU3HFXEk0R8o86WvUD64aINhv5K3oRmpJXkw8uxMG6Hh6JY9X7OwGSqfUy9tDG3sHNoEi0d_d_fv9qndxRU0VClFqo3KVo3U655Hnt1PXB3Qra2Y2QGdEwgTAMCxopsoxOe6SD0gD8movDhT0LAnhqlE8gVCpLWnRoV7OJCkFAwEXitrYL1W7p7pbiE_P7XH6E_rihODm5s52XtiH9Ekaw0VgI9exadWL1uoEYjPtg2672k5szsxbKyWB2fdT0w5Y_0hcT8oXOlRetmLS8-g-6TLXXQgYAAA==)):
Button
{@render children?.()}
{@render children?.()}
App
Hover me
Hover me
## Controlling when attachments re-run
Attachments, unlike [actions](use), are fully reactive: `{@attach foo(bar)}`
will re-run on changes to `foo` _or_ `bar` (or any state read inside `foo`):
function foo(bar) {
return (node) => {
veryExpensiveSetupWork(node);
update(node, bar);
};
}
In the rare case that this is a problem (for example, if `foo` does expensive
and unavoidable setup work) consider passing the data inside a function and
reading it in a child effect:
function foo(getBar) {
return (node) => {
veryExpensiveSetupWork(node);
namespace $effect
namespace $effect
Runs code when a component is mounted to the DOM, and then whenever its
dependencies change, i.e. `$state` or `$derived` values. The timing of the
execution is after the DOM has been updated.
Example:
$effect(() => console.log('The count is now ' + count));
If you return a function from the effect, it will be called right before the
effect is run again, or when the component is unmounted.
Does not run during server side rendering.
[https://svelte.dev/docs/svelte/$effect]($effect)
@paramfn The function to execute
$effect(() => { update(`node: any`node, `getBar: any`getBar()); }); } }
## Creating attachments programmatically
To add attachments to an object that will be spread onto a component or
element, use [`createAttachmentKey`](svelte-attachments#createAttachmentKey).
## Converting actions to attachments
If you’re using a library that only provides actions, you can convert them to
attachments with [`fromAction`](svelte-attachments#fromAction), allowing you
to (for example) use them with components.
# {@const ...}
### On this page
* [{@const ...}](@const)
The `{@const ...}` tag defines a local constant.
{#each boxes as box}
{@const area = box.width * box.height}
{box.width} * {box.height} = {area}
{/each}
`{@const}` is only allowed as an immediate child of a block — `{#if ...}`,
`{#each ...}`, `{#snippet ...}` and so on — a ` ` or a
``.
# {@debug ...}
### On this page
* [{@debug ...}](@debug)
The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs
the values of specific variables whenever they change, and pauses code
execution if you have devtools open.
{@debug user}
Hello {user.firstname}!
`{@debug ...}` accepts a comma-separated list of variable names (not arbitrary
expressions).
{@debug user}
{@debug user1, user2, user3}
{@debug user.firstname}
{@debug myArray[0]}
{@debug !isReady}
{@debug typeof user === 'object'}
The `{@debug}` tag without any arguments will insert a `debugger` statement
that gets triggered when _any_ state changes, as opposed to the specified
variables.
# {@html ...}
### On this page
* [{@html ...}](@html)
* Styling
To inject raw HTML into your component, use the `{@html ...}` tag:
{@html content}
> Make sure that you either escape the passed string or only populate it with
> values that are under your control in order to prevent [XSS
> attacks](https://owasp.org/www-community/attacks/xss/). Never render
> unsanitized content.
The expression should be valid standalone HTML — this will not work, because
`` is not valid HTML:
{@html ''}content{@html '
'}
It also will not compile Svelte code.
## Styling
Content rendered this way is ‘invisible’ to Svelte and as such will not
receive [scoped styles](scoped-styles) — in other words, this will not work,
and the `a` and `img` styles will be regarded as unused:
{@html content}
Instead, use the `:global` modifier to target everything inside the
``:
# {@render ...}
### On this page
* [{@render ...}](@render)
* Optional snippets
To render a [snippet](snippet), use a `{@render ...}` tag.
{#snippet sum(a, b)}
{a} + {b} = {a + b}
{/snippet}
{@render sum(1, 2)}
{@render sum(3, 4)}
{@render sum(5, 6)}
The expression can be an identifier like `sum`, or an arbitrary JavaScript
expression:
{@render (cool ? coolSnippet : lameSnippet)()}
## Optional snippets
If the snippet is potentially undefined — for example, because it’s an
incoming prop — then you can use optional chaining to only render it when it
_is_ defined:
{@render children?.()}
Alternatively, use an [`{#if ...}`](if) block with an `:else` clause to render
fallback content:
{#if children}
{@render children()}
{:else}
fallback content
{/if}
# animate:
### On this page
* [animate:](animate)
* Animation Parameters
* Custom animation functions
An animation is triggered when the contents of a [keyed each
block](each#Keyed-each-blocks) are re-ordered. Animations do not run when an
element is added or removed, only when the index of an existing data item
within the each block changes. Animate directives must be on an element that
is an _immediate_ child of a keyed each block.
Animations can be used with Svelte’s [built-in animation functions](svelte-
animate) or custom animation functions.
{#each list as item, index (item)}
{item}
{/each}
## Animation Parameters
As with actions and transitions, animations can have parameters.
(The double `{{curlies}}` aren’t a special syntax; this is an object literal
inside an expression tag.)
{#each list as item, index (item)}
{item}
{/each}
## Custom animation functions
animation = (node: HTMLElement, { from: DOMRect, to: DOMRect } , params: any) => {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
Animations can use custom functions that provide the `node`, an `animation`
object and any `parameters` as arguments. The `animation` parameter is an
object containing `from` and `to` properties each containing a
[DOMRect](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect#Properties)
describing the geometry of the element in its `start` and `end` positions. The
`from` property is the DOMRect of the element in its starting position, and
the `to` property is the DOMRect of the element in its final position after
the list has been reordered and the DOM updated.
If the returned object has a `css` method, Svelte will create a [web
animation](https://developer.mozilla.org/en-
US/docs/Web/API/Web_Animations_API) that plays on the element.
The `t` argument passed to `css` is a value that goes from `0` and `1` after
the `easing` function has been applied. The `u` argument is equal to `1 - t`.
The function is called repeatedly _before_ the animation begins, with
different `t` and `u` arguments.
App
{#each list as item, index (item)}
{item}
{/each}
{#each list as item, index (item)}
{item}
{/each}
A custom animation function can also return a `tick` function, which is called
_during_ the animation with the same `t` and `u` arguments.
> If it’s possible to use `css` instead of `tick`, do so — web animations can
> run off the main thread, preventing jank on slower devices.
App
{#each list as item, index (item)}
{item}
{/each}
{#each list as item, index (item)}
{item}
{/each}
# {#await ...}
### On this page
* [{#await ...}](await)
{#await expression}...{:then name}...{:catch name}...{/await}
{#await expression}...{:then name}...{/await}
{#await expression then name}...{/await}
{#await expression catch name}...{/await}
Await blocks allow you to branch on the three possible states of a
[`Promise`](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — pending, fulfilled
or rejected.
{#await promise}
waiting for the promise to resolve...
{:then value}
The value is {value}
{:catch error}
Something went wrong: {error.message}
{/await}
> During server-side rendering, only the pending branch will be rendered.
>
> If the provided expression is not a `Promise`, only the `:then` branch will
> be rendered, including during server-side rendering.
The `catch` block can be omitted if you don’t need to render anything when the
promise rejects (or no error is possible).
{#await promise}
waiting for the promise to resolve...
{:then value}
The value is {value}
{/await}
If you don’t care about the pending state, you can also omit the initial
block.
{#await promise then value}
The value is {value}
{/await}
Similarly, if you only want to show the error state, you can omit the `then`
block.
{#await promise catch error}
The error is {error}
{/await}
> You can use `#await` with [`import(...)`](https://developer.mozilla.org/en-
> US/docs/Web/JavaScript/Reference/Operators/import) to render components
> lazily:
>
>
> {#await import('./Component.svelte') then { default: Component }}
>
> {/await}
# Basic markup
### On this page
* [Basic markup](basic-markup)
* Tags
* Element attributes
* Component props
* Spread attributes
* Events
* Text expressions
* Comments
Markup inside a Svelte component can be thought of as HTML++.
## Tags
A lowercase tag, like ``, denotes a regular HTML element. A capitalised
tag or a tag that uses dot notation, such as `
` or ``,
indicates a _component_.
## Element attributes
By default, attributes work exactly like their HTML counterparts.
can't touch this
As in HTML, values may be unquoted.
Attribute values can contain JavaScript expressions.
page {p}
Or they can _be_ JavaScript expressions.
...
Boolean attributes are included on the element if their value is
[truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) and
excluded if it’s [falsy](https://developer.mozilla.org/en-
US/docs/Glossary/Falsy).
All other attributes are included unless their value is
[nullish](https://developer.mozilla.org/en-US/docs/Glossary/Nullish) (`null`
or `undefined`).
This div has no title attribute
> Quoting a singular expression does not affect how the value is parsed, but
> in Svelte 6 it will cause the value to be coerced to a string:
>
>
> ...
When the attribute name and value match (`name={name}`), they can be replaced
with `{name}`.
...
## Component props
By convention, values passed to components are referred to as _properties_ or
_props_ rather than _attributes_ , which are a feature of the DOM.
As with elements, `name={name}` can be replaced with the `{name}` shorthand.
## Spread attributes
_Spread attributes_ allow many attributes or properties to be passed to an
element or component at once.
An element or component can have multiple spread attributes, interspersed with
regular ones. Order matters — if `things.a` exists it will take precedence
over `a="b"`, while `c="d"` would take precedence over `things.c`:
## Events
Listening to DOM events is possible by adding attributes to the element that
start with `on`. For example, to listen to the `click` event, add the
`onclick` attribute to a button:
console.log('clicked')}>click me
Event attributes are case sensitive. `onclick` listens to the `click` event,
`onClick` listens to the `Click` event, which is different. This ensures you
can listen to custom events that have uppercase characters in them.
Because events are just attributes, the same rules as for attributes apply:
* you can use the shorthand form: `click me `
* you can spread them: `click me `
Timing-wise, event attributes always fire after events from bindings (e.g.
`oninput` always fires after an update to `bind:value`). Under the hood, some
event handlers are attached directly with `addEventListener`, while others are
_delegated_.
When using `ontouchstart` and `ontouchmove` event attributes, the handlers are
[passive](https://developer.mozilla.org/en-
US/docs/Web/API/EventTarget/addEventListener#using_passive_listeners) for
better performance. This greatly improves responsiveness by allowing the
browser to scroll the document immediately, rather than waiting to see if the
event handler calls `event.preventDefault()`.
In the very rare cases that you need to prevent these event defaults, you
should use [`on`](svelte-events#on) instead (for example inside an action).
### Event delegation
To reduce memory footprint and increase performance, Svelte uses a technique
called event delegation. This means that for certain events — see the list
below — a single event listener at the application root takes responsibility
for running any handlers on the event’s path.
There are a few gotchas to be aware of:
* when you manually dispatch an event with a delegated listener, make sure to set the `{ bubbles: true }` option or it won’t reach the application root
* when using `addEventListener` directly, avoid calling `stopPropagation` or the event won’t reach the application root and handlers won’t be invoked. Similarly, handlers added manually inside the application root will run _before_ handlers added declaratively deeper in the DOM (with e.g. `onclick={...}`), in both capturing and bubbling phases. For these reasons it’s better to use the `on` function imported from `svelte/events` rather than `addEventListener`, as it will ensure that order is preserved and `stopPropagation` is handled correctly.
The following event handlers are delegated:
* `beforeinput`
* `click`
* `change`
* `dblclick`
* `contextmenu`
* `focusin`
* `focusout`
* `input`
* `keydown`
* `keyup`
* `mousedown`
* `mousemove`
* `mouseout`
* `mouseover`
* `mouseup`
* `pointerdown`
* `pointermove`
* `pointerout`
* `pointerover`
* `pointerup`
* `touchend`
* `touchmove`
* `touchstart`
## Text expressions
A JavaScript expression can be included as text by surrounding it with curly
braces.
{expression}
Expressions that are `null` or `undefined` will be omitted; all others are
[coerced to strings](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion).
Curly braces can be included in a Svelte template by using their [HTML
entity](https://developer.mozilla.org/docs/Glossary/Entity) strings:
`{`, `{`, or `{` for `{` and `}`, `}`, or
`}` for `}`.
If you’re using a regular expression (`RegExp`) [literal
notation](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#literal_notation_and_constructor),
you’ll need to wrap it in parentheses.
Hello {name}!
{a} + {b} = {a + b}.
{(/^[A-Za-z ]+$/).test(value) ? x : y}
The expression will be stringified and escaped to prevent code injections. If
you want to render HTML, use the `{@html}` tag instead.
{@html potentiallyUnsafeHtmlString}
> Make sure that you either escape the passed string or only populate it with
> values that are under your control in order to prevent [XSS
> attacks](https://owasp.org/www-community/attacks/xss/)
## Comments
You can use HTML comments inside components.
Hello world
Comments beginning with `svelte-ignore` disable warnings for the next block of
markup. Usually, these are accessibility warnings; make sure that you’re
disabling them for a good reason.
You can add a special comment starting with `@component` that will show up
when hovering over the component name in other files.
Hello, {name}
# bind:
### On this page
* [bind:](bind)
* Function bindings
*
*
*
*
*
*
*
*
*
*
* window and document
* Contenteditable bindings
* Dimensions
* bind:this
* bind:_property_ for components
Data ordinarily flows down, from parent to child. The `bind:` directive allows
data to flow the other way, from child to parent.
The general syntax is `bind:property={expression}`, where `expression` is an
[_lvalue_](https://press.rebus.community/programmingfundamentals/chapter/lvalue-
and-rvalue/) (i.e. a variable or an object property). When the expression is
an identifier with the same name as the property, we can omit the expression —
in other words these are equivalent:
Svelte creates an event listener that updates the bound value. If an element
already has a listener for the same event, that listener will be fired before
the bound value is updated.
Most bindings are _two-way_ , meaning that changes to the value will affect
the element and vice versa. A few bindings are _readonly_ , meaning that
changing their value will have no effect on the element.
## Function bindings
You can also use `bind:property={get, set}`, where `get` and `set` are
functions, allowing you to perform validation and transformation:
value,
(v) => value = v.toLowerCase()}
/>
In the case of readonly bindings like dimension bindings, the `get` value
should be `null`:
...
> Function bindings are available in Svelte 5.9.0 and newer.
##
A `bind:value` directive on an ` ` element binds the input’s `value`
property:
{message}
In the case of a numeric input (`type="number"` or `type="range"`), the value
will be coerced to a number
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE6WPwYoCMQxAfyWEPeyiOOqx2w74Hds9pBql0IllmhGXYf5dKqwiyILsLXnwwsuI-5i4oPkaUX8yo7kCnKNQV7dNzoty4qSVBSr8jG-
Poixa0KAt2z5mbb14TaxA4OCtKCm_rz4-f2m403WltrlrYhMFTtcLNkoeFGqZ8yhDF7j3CCHKzpwoDexGmqCL4jwuPUJHZ-
dxVcfmyYGe5MAv-La5pbxYFf5Z9Zf_UJXb-
sEMquFgJJhBmGyTW5yj8lnRaD_w9D1dAKSSj7zqAQAA)):
{a} + {b} = {a + b}
If the input is empty or invalid (in the case of `type="number"`), the value
is `undefined`.
Since 5.6.0, if an ` ` has a `defaultValue` and is part of a form, it
will revert to that value instead of the empty string when the form is reset.
Note that for the initial render the value of the binding takes precedence
unless it is `null` or `undefined`.
> Use reset buttons sparingly, and ensure that users won’t accidentally click
> them while trying to submit the form.
##
Checkbox and radio inputs can be bound with `bind:checked`:
Accept terms and conditions
Since 5.6.0, if an ` ` has a `defaultChecked` attribute and is part of a
form, it will revert to that value instead of `false` when the form is reset.
Note that for the initial render the value of the binding takes precedence
unless it is `null` or `undefined`.
##
Checkboxes can be in an [indeterminate](https://developer.mozilla.org/en-
US/docs/Web/API/HTMLInputElement/indeterminate) state, independently of
whether they are checked or unchecked:
##
Inputs that work together can use `bind:group`
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE62T32_TMBDH_5XDQkpbrct7SCMGEvCEECDxsO7BSW6L2c227EvbKOv_jp0f6jYhQKJv5_P3PvdL1wstH1Bk4hMSGdgbRzUssFaM9VJciFtF6EV23QvubNRFR_BPUVfWXvodEkdfKT3-zl8Zzag5YETuK6csF1u9ZUIGNo4VkYQNvPYsGRfJF5JKJ8s3QRJE6WoFb2Nq6K-ck13u2Sl9Vxxhlc6QUBIFnz9Brm9ifJ6esun81XoNd860FmtwslYGlLYte5AO4aHlVhJ1gIeKWq92COt1iMtJlkhFPkgh1rHZiiF6K6BUus4G5KafGznCTlIbVUMfQZUWMJh5OrL-
C_qjMYSwb1DyiH7iOEuCb1ZpWTUjfHqcwC_GWDVY3ZfmME_SGttSmD9IHaYatvWHIc6xLyqad3mq6KuqcCwnWn9p8p-p71BqP2IH81zc9w2in-
od7XORP7ayCpd5YCeXI_-p59mObPF9WmwGpx3nqS2Gzw8TO3zOaS5_GqUXyQUkS3h8hOSz0ZhMESHGc0c4Hm3MAn00t1wrb0l2GZRkqvt4sXwczm6Qh8vnUJzI2LV4vAkvqWgfehTZrSSPx19WiVfFfAQAAA==)):
BurritoChooser
Plain
Whole wheat
Spinach
Rice
Beans
Cheese
Guac (extra)
Plain
Whole wheat
Spinach
Rice
Beans
Cheese
Guac (extra)
> `bind:group` only works if the inputs are in the same Svelte component.
##
On ` ` elements with `type="file"`, you can use `bind:files` to get the
[`FileList` of selected files](https://developer.mozilla.org/en-
US/docs/Web/API/FileList). When you want to update the files programmatically,
you always need to use a `FileList` object. Currently `FileList` objects
cannot be constructed directly, so you need to create a new
[`DataTransfer`](https://developer.mozilla.org/en-
US/docs/Web/API/DataTransfer) object and get `files` from there.
Upload a picture:
clear
`FileList` objects also cannot be modified, so if you want to e.g. delete a
single file from the list, you need to create a new `DataTransfer` object and
add the files you want to keep.
> `DataTransfer` may not be available in server-side JS runtimes. Leaving the
> state that is bound to `files` uninitialized prevents potential errors if
> components are server-side rendered.
##
A `` value binding corresponds to the `value` property on the selected
``, which can be any value (not just strings, as is normally the case
in the DOM).
a
b
c
A `` element behaves similarly to a checkbox group. The bound
variable is an array with an entry corresponding to the `value` property of
each selected ``.
Rice
Beans
Cheese
Guac (extra)
When the value of an ` ` matches its text content, the attribute can be
omitted.
Rice
Beans
Cheese
Guac (extra)
You can give the `` a default value by adding a `selected` attribute
to the`` (or options, in the case of ``) that should
be initially selected. If the `` is part of a form, it will revert to
that selection when the form is reset. Note that for the initial render the
value of the binding takes precedence if it’s not `undefined`.
a
b
c
##
`` elements have their own set of bindings — five two-way ones...
* [`currentTime`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentTime)
* [`playbackRate`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/playbackRate)
* [`paused`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/paused)
* [`volume`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/volume)
* [`muted`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/muted)
...and six readonly ones:
* [`duration`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/duration)
* [`buffered`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered)
* [`seekable`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seekable)
* [`seeking`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seeking_event)
* [`ended`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/ended)
* [`readyState`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState)
* [`played`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/played)
##
`` elements have all the same bindings as `` elements, plus
readonly [`videoWidth`](https://developer.mozilla.org/en-
US/docs/Web/API/HTMLVideoElement/videoWidth) and
[`videoHeight`](https://developer.mozilla.org/en-
US/docs/Web/API/HTMLVideoElement/videoHeight) bindings.
##
` ` elements have two readonly bindings:
* [`naturalWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth)
* [`naturalHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalHeight)
##
`` elements support binding to the `open` property.
How do you comfort a JavaScript bug?
You console it.
## window and document
To bind to properties of `window` and `document`, see
[``](svelte-window) and [``](svelte-document).
## Contenteditable bindings
Elements with the `contenteditable` attribute support the following bindings:
* [`innerHTML`](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML)
* [`innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText)
* [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
> There are [subtle differences between `innerText` and
> `textContent`](https://developer.mozilla.org/en-
> US/docs/Web/API/Node/textContent#differences_from_innertext).
## Dimensions
All visible elements have the following readonly bindings, measured with a
`ResizeObserver`:
* [`clientWidth`](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth)
* [`clientHeight`](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight)
* [`offsetWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth)
* [`offsetHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight)
* [`contentRect`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentRect)
* [`contentBoxSize`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentBoxSize)
* [`borderBoxSize`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/borderBoxSize)
* [`devicePixelContentBoxSize`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/devicePixelContentBoxSize)
> `display: inline` elements do not have a width or height (except for
> elements with ‘intrinsic’ dimensions, like ` ` and ``), and
> cannot be observed with a `ResizeObserver`. You will need to change the
> `display` style of these elements to something else, such as `inline-block`.
> Note that CSS transformations do not trigger `ResizeObserver` callbacks.
## bind:this
bind:this={dom_node}
To get a reference to a DOM node, use `bind:this`. The value will be
`undefined` until the component is mounted — in other words, you should read
it inside an effect or an event handler, but not during component
initialisation:
Components also support `bind:this`, allowing you to interact with component
instances programmatically.
App
cart.empty()}> Empty shopping cart
ShoppingCart
## bind:_property_ for components
bind:property={variable}
You can bind to component props using the same syntax as for elements.
While Svelte props are reactive without binding, that reactivity only flows
downward into the component by default. Using `bind:property` allows changes
to the property from within the component to flow back up out of the
component.
To mark a property as bindable, use the [`$bindable`]($bindable) rune:
Declaring a property as bindable means it _can_ be used using `bind:`, not
that it _must_ be used using `bind:`.
Bindable properties can have a fallback value:
This fallback value _only_ applies when the property is _not_ bound. When the
property is bound and a fallback value is present, the parent is expected to
provide a value other than `undefined`, else a runtime error is thrown. This
prevents hard-to-reason-about situations where it’s unclear which value should
apply.
# class
### On this page
* [class](class)
* Attributes
* The class: directive
There are two ways to set classes on elements: the `class` attribute, and the
`class:` directive.
## Attributes
Primitive values are treated like any other attribute:
...
> For historical reasons, falsy values (like `false` and `NaN`) are
> stringified (`class="false"`), though `class={undefined}` (or `null`) cause
> the attribute to be omitted altogether. In a future version of Svelte, all
> falsy values will cause `class` to be omitted.
### Objects and arrays
Since Svelte 5.16, `class` can be an object or array, and is converted to a
string using [clsx](https://github.com/lukeed/clsx).
If the value is an object, the truthy keys are added:
...
If the value is an array, the truthy values are combined:
...
Note that whether we’re using the array or object form, we can set multiple
classes simultaneously with a single condition, which is particularly useful
if you’re using things like Tailwind.
Arrays can contain arrays and objects, and clsx will flatten them. This is
useful for combining local classes with props, for example:
Button
{@render props.children?.()}
{@render props.children?.()}
The user of this component has the same flexibility to use a mixture of
objects, arrays and strings:
App
useTailwind = true}
class={{ 'bg-blue-700 sm:w-1/2': useTailwind }}
>
Accept the inevitability of Tailwind
useTailwind = true}
class={{ 'bg-blue-700 sm:w-1/2': useTailwind }}
>
Accept the inevitability of Tailwind
Svelte also exposes the `ClassValue` type, which is the type of value that the
`class` attribute on elements accept. This is useful if you want to use a
type-safe class name in component props:
...
## The class: directive
Prior to Svelte 5.16, the `class:` directive was the most convenient way to
set classes on elements conditionally.
...
...
As with other directives, we can use a shorthand when the name of the class
coincides with the value:
...
> Unless you’re using an older version of Svelte, consider avoiding `class:`,
> since the attribute is more powerful and composable.
# Compiler errors
### On this page
* [Compiler errors](compiler-errors)
### animation_duplicate
An element can only have one 'animate' directive
### animation_invalid_placement
An element that uses the `animate:` directive must be the only child of a keyed `{#each ...}` block
### animation_missing_key
An element that uses the `animate:` directive must be the only child of a keyed `{#each ...}` block. Did you forget to add a key to your each block?
### attribute_contenteditable_dynamic
'contenteditable' attribute cannot be dynamic if element uses two-way binding
### attribute_contenteditable_missing
'contenteditable' attribute is required for textContent, innerHTML and innerText two-way bindings
### attribute_duplicate
Attributes need to be unique
### attribute_empty_shorthand
Attribute shorthand cannot be empty
### attribute_invalid_event_handler
Event attribute must be a JavaScript expression, not a string
### attribute_invalid_multiple
'multiple' attribute must be static if select uses two-way binding
### attribute_invalid_name
'%name%' is not a valid attribute name
### attribute_invalid_sequence_expression
Sequence expressions are not allowed as attribute/directive values in runes mode, unless wrapped in parentheses
### attribute_invalid_type
'type' attribute must be a static text value if input uses two-way binding
### attribute_unquoted_sequence
Attribute values containing `{...}` must be enclosed in quote marks, unless the value only contains the expression
### bind_group_invalid_expression
`bind:group` can only bind to an Identifier or MemberExpression
### bind_group_invalid_snippet_parameter
Cannot `bind:group` to a snippet parameter
### bind_invalid_expression
Can only bind to an Identifier or MemberExpression or a `{get, set}` pair
### bind_invalid_name
`bind:%name%` is not a valid binding
`bind:%name%` is not a valid binding. %explanation%
### bind_invalid_parens
`bind:%name%={get, set}` must not have surrounding parentheses
### bind_invalid_target
`bind:%name%` can only be used with %elements%
### bind_invalid_value
Can only bind to state or props
### bindable_invalid_location
`$bindable()` can only be used inside a `$props()` declaration
### block_duplicate_clause
%name% cannot appear more than once within a block
### block_invalid_continuation_placement
{:...} block is invalid at this position (did you forget to close the preceding element or block?)
### block_invalid_elseif
'elseif' should be 'else if'
### block_invalid_placement
{#%name% ...} block cannot be %location%
### block_unclosed
Block was left open
### block_unexpected_character
Expected a `%character%` character immediately following the opening bracket
### block_unexpected_close
Unexpected block closing tag
### component_invalid_directive
This type of directive is not valid on components
### const_tag_cycle
Cyclical dependency detected: %cycle%
### const_tag_invalid_expression
{@const ...} must consist of a single variable declaration
### const_tag_invalid_placement
`{@const}` must be the immediate child of `{#snippet}`, `{#if}`, `{:else if}`, `{:else}`, `{#each}`, `{:then}`, `{:catch}`, ``, ``
### constant_assignment
Cannot assign to %thing%
### constant_binding
Cannot bind to %thing%
### css_empty_declaration
Declaration cannot be empty
### css_expected_identifier
Expected a valid CSS identifier
### css_global_block_invalid_combinator
A `:global` selector cannot follow a `%name%` combinator
### css_global_block_invalid_declaration
A top-level `:global {...}` block can only contain rules, not declarations
### css_global_block_invalid_list
A `:global` selector cannot be part of a selector list with entries that don't contain `:global`
The following CSS is invalid:
:global, x {
y {
color: red;
}
}
This is mixing a `:global` block, which means “everything in here is
unscoped”, with a scoped selector (`x` in this case). As a result it’s not
possible to transform the inner selector (`y` in this case) into something
that satisfies both requirements. You therefore have to split this up into two
selectors:
:global {
y {
color: red;
}
}
x y {
color: red;
}
### css_global_block_invalid_modifier
A `:global` selector cannot modify an existing selector
### css_global_block_invalid_modifier_start
A `:global` selector can only be modified if it is a descendant of other selectors
### css_global_block_invalid_placement
A `:global` selector cannot be inside a pseudoclass
### css_global_invalid_placement
`:global(...)` can be at the start or end of a selector sequence, but not in the middle
### css_global_invalid_selector
`:global(...)` must contain exactly one selector
### css_global_invalid_selector_list
`:global(...)` must not contain type or universal selectors when used in a compound selector
### css_nesting_selector_invalid_placement
Nesting selectors can only be used inside a rule or as the first selector inside a lone `:global(...)`
### css_selector_invalid
Invalid selector
### css_type_selector_invalid_placement
`:global(...)` must not be followed by a type selector
### debug_tag_invalid_arguments
{@debug ...} arguments must be identifiers, not arbitrary expressions
### declaration_duplicate
`%name%` has already been declared
### declaration_duplicate_module_import
Cannot declare a variable with the same name as an import inside `
{#each array as entry}
entry = 4}>change
{/each}
This turned out to be buggy and unpredictable, particularly when working with
derived values (such as `array.map(...)`), and as such is forbidden in runes
mode. You can achieve the same outcome by using the index instead:
{#each array as entry, i}
array[i] = 4}>change
{/each}
### effect_invalid_placement
`$effect()` can only be used as an expression statement
### element_invalid_closing_tag
`%name%>` attempted to close an element that was not open
### element_invalid_closing_tag_autoclosed
`%name%>` attempted to close element that was already automatically closed by `<%reason%>` (cannot nest `<%reason%>` inside `<%name%>`)
### element_unclosed
`<%name%>` was left open
### event_handler_invalid_component_modifier
Event modifiers other than 'once' can only be used on DOM elements
### event_handler_invalid_modifier
Valid event modifiers are %list%
### event_handler_invalid_modifier_combination
The '%modifier1%' and '%modifier2%' modifiers cannot be used together
### expected_attribute_value
Expected attribute value
### expected_block_type
Expected 'if', 'each', 'await', 'key' or 'snippet'
### expected_identifier
Expected an identifier
### expected_pattern
Expected identifier or destructure pattern
### expected_token
Expected token %token%
### expected_whitespace
Expected whitespace
### export_undefined
`%name%` is not defined
### global_reference_invalid
`%name%` is an illegal variable name. To reference a global variable called `%name%`, use `globalThis.%name%`
### host_invalid_placement
`$host()` can only be used inside custom element component instances
### illegal_element_attribute
`<%name%>` does not support non-event attributes or spread attributes
### import_svelte_internal_forbidden
Imports of `svelte/internal/*` are forbidden. It contains private runtime code which is subject to change without notice. If you're importing from `svelte/internal/*` to work around a limitation of Svelte, please open an issue at https://github.com/sveltejs/svelte and explain your use case
### inspect_trace_generator
`$inspect.trace(...)` cannot be used inside a generator function
### inspect_trace_invalid_placement
`$inspect.trace(...)` must be the first statement of a function body
### invalid_arguments_usage
The arguments keyword cannot be used within the template or at the top level of a component
### js_parse_error
%message%
### legacy_export_invalid
Cannot use `export let` in runes mode — use `$props()` instead
### legacy_props_invalid
Cannot use `$$props` in runes mode
### legacy_reactive_statement_invalid
`$:` is not allowed in runes mode, use `$derived` or `$effect` instead
### legacy_rest_props_invalid
Cannot use `$$restProps` in runes mode
### let_directive_invalid_placement
`let:` directive at invalid position
### mixed_event_handler_syntaxes
Mixing old (on:%name%) and new syntaxes for event handling is not allowed. Use only the on%name% syntax
### module_illegal_default_export
A component cannot have a default export
### node_invalid_placement
%message%. The browser will 'repair' the HTML (by moving, removing, or inserting elements) which breaks Svelte's assumptions about the structure of your components.
HTML restricts where certain elements can appear. In case of a violation the
browser will ‘repair’ the HTML in a way that breaks Svelte’s assumptions about
the structure of your components. Some examples:
* `hello
world
` will result in `hello
world
` (the `` autoclosed the `
` because `
` cannot contain block-level elements)
* `option a
` will result in `option a ` (the `
` is removed)
* `
` will result in `
` (a `
` is auto-inserted)
### options_invalid_value
Invalid compiler option: %details%
### options_removed
Invalid compiler option: %details%
### options_unrecognised
Unrecognised compiler option %keypath%
### props_duplicate
Cannot use `%rune%()` more than once
### props_id_invalid_placement
`$props.id()` can only be used at the top level of components as a variable declaration initializer
### props_illegal_name
Declaring or accessing a prop starting with `$$` is illegal (they are reserved for Svelte internals)
### props_invalid_identifier
`$props()` can only be used with an object destructuring pattern
### props_invalid_pattern
`$props()` assignment must not contain nested properties or computed keys
### props_invalid_placement
`$props()` can only be used at the top level of components as a variable declaration initializer
### reactive_declaration_cycle
Cyclical dependency detected: %cycle%
### render_tag_invalid_call_expression
Calling a snippet function using apply, bind or call is not allowed
### render_tag_invalid_expression
`{@render ...}` tags can only contain call expressions
### render_tag_invalid_spread_argument
cannot use spread arguments in `{@render ...}` tags
### rune_invalid_arguments
`%rune%` cannot be called with arguments
### rune_invalid_arguments_length
`%rune%` must be called with %args%
### rune_invalid_computed_property
Cannot access a computed property of a rune
### rune_invalid_name
`%name%` is not a valid rune
### rune_invalid_spread
`%rune%` cannot be called with a spread argument
### rune_invalid_usage
Cannot use `%rune%` rune in non-runes mode
### rune_missing_parentheses
Cannot use rune without parentheses
### rune_removed
The `%name%` rune has been removed
### rune_renamed
`%name%` is now `%replacement%`
### runes_mode_invalid_import
%name% cannot be used in runes mode
### script_duplicate
A component can have a single top-level `
{#snippet greeting(name)}
{message} {name}!
{/snippet}
...because `greeting` references `message`, which is defined in the second
`
This value updates: {reactive}
This value does not update: {stale}
{
stale = 'updated';
reactive = 'updated';
}}>update
To fix this, wrap your variable declaration with `$state`.
### options_deprecated_accessors
The `accessors` option has been deprecated. It will have no effect in runes mode
### options_deprecated_immutable
The `immutable` option has been deprecated. It will have no effect in runes mode
### options_missing_custom_element
The `customElement` option is used when generating a custom element. Did you forget the `customElement: true` compile option?
### options_removed_enable_sourcemap
The `enableSourcemap` option has been removed. Source maps are always generated now, and tooling can choose to ignore them
### options_removed_hydratable
The `hydratable` option has been removed. Svelte components are always hydratable now
### options_removed_loop_guard_timeout
The `loopGuardTimeout` option has been removed
### options_renamed_ssr_dom
`generate: "dom"` and `generate: "ssr"` options have been renamed to "client" and "server" respectively
### perf_avoid_inline_class
Avoid 'new class' — instead, declare the class at the top level scope
### perf_avoid_nested_class
Avoid declaring classes below the top level scope
### reactive_declaration_invalid_placement
Reactive declarations only exist at the top level of the instance script
### reactive_declaration_module_script_dependency
Reassignments of module-level declarations will not cause reactive statements to update
### script_context_deprecated
`context="module"` is deprecated, use the `module` attribute instead
### script_unknown_attribute
Unrecognized attribute — should be one of `generics`, `lang` or `module`. If this exists for a preprocessor, ensure that the preprocessor removes it
### slot_element_deprecated
Using `` to render parent content is deprecated. Use `{@render ...}` tags instead
See [the migration guide](v5-migration-guide#Snippets-instead-of-slots) for
more info.
### state_referenced_locally
This reference only captures the initial value of `%name%`. Did you mean to reference it inside a %type% instead?
This warning is thrown when the compiler detects the following:
* A reactive variable is declared
* ...and later reassigned...
* ...and referenced in the same scope
This ‘breaks the link’ to the original state declaration. For example, if you
pass the state to a function, the function loses access to the state once it
is reassigned:
Parent
count++}>
increment
count++}>
increment
Child
The count is {count}
The count is {count}
To fix this, reference the variable such that it is lazily evaluated. For the
above example, this can be achieved by wrapping `count` in a function:
Parent
count++}>
increment
count++}>
increment
Child
The count is {count()}
The count is {count()}
For more info, see [Passing state into functions]($state#Passing-state-into-
functions).
### store_rune_conflict
It looks like you're using the `$%name%` rune, but there is a local binding called `%name%`. Referencing a local variable with a `$` prefix will create a store subscription. Please rename `%name%` to avoid the ambiguity
### svelte_component_deprecated
`` is deprecated in runes mode — components are dynamic by default
In previous versions of Svelte, the component constructor was fixed when the
component was rendered. In other words, if you wanted `` to re-render when
`X` changed, you would either have to use `` or put
the component inside a `{#key X}...{/key}` block.
In Svelte 5 this is no longer true — if `X` changes, `` re-renders.
In some cases `` syntax can be used as a replacement; a
lowercased variable with property access is recognized as a component in
Svelte 5.
For complex component resolution logic, an intermediary, capitalized variable
may be necessary. E.g. in places where `@const` can be used:
{#each items as item}
{@const Component = item.condition ? Y : Z}
{/each}
A derived value may be used in other contexts:
### svelte_element_invalid_this
`this` should be an `{expression}`. Using a string attribute value will cause an error in future versions of Svelte
### svelte_self_deprecated
`` is deprecated — use self-imports (e.g. `import %name% from './%basename%'`) instead
See [the note in the docs](legacy-svelte-self) for more info.
### unknown_code
`%code%` is not a recognised code
`%code%` is not a recognised code (did you mean `%suggestion%`?)
# Context
### On this page
* [Context](context)
* Using context with state
* Type-safe context
* Replacing global state
Context allows components to access values owned by parent components without
passing them down as props (potentially through many layers of intermediate
components, known as ‘prop-drilling’). The parent component sets context with
`setContext(key, value)`...
Parent
...and the child retrieves it with `getContext`:
Child
{message}, inside Child.svelte
{message}, inside Child.svelte
This is particularly useful when `Parent.svelte` is not directly aware of
`Child.svelte`, but instead renders it as part of a `children`
[snippet](snippet)
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE42Q3W6DMAyFX8WyJgESK-
oto6hTX2D3YxcM3IIUQpR40yqUd58CrCXsp7tL7HNsf2dAWXaEKR56yfTBGOOxFWQwfR6Qz8q1XAHjL-
GjUhvzToJd7bU09FO9ctMkG0wxM5VuFeeFLLjtVK8ZnkpNkuGo-w6CTTJ9Z3PwsBAemlbUF934W8iy5DpaZtOUcU02-ZLcaS51jHEkTFm_kY1_wfOO8QnXrb8hBzDEc6pgZ4gFoyz4KgiD7nxfTe8ghqAhIfrJ46cTzVZBbkPlODVJsLCDO6V7ZcJoncyw1yRr0hd1GNn_ZbEM3I9i1bmVxOlWElUvDUNHxpQngt3C4CXzjS1rtvkw22wMrTRtTbC8Lkuabe7jvthPPe3DofYCAAA=)):
The key (`'my-context'`, in the example above) and the context itself can be
any JavaScript value.
In addition to [`setContext`](svelte#setContext) and
[`getContext`](svelte#getContext), Svelte exposes
[`hasContext`](svelte#hasContext) and
[`getAllContexts`](svelte#getAllContexts) functions.
## Using context with state
You can store reactive state in context
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE41R0W6DMAz8FSuaBNUQdK8MkKZ-
wh7HHihzu6hgosRMm1D-fUpSVNq12x4iEvvOx_kmQU2PIhfP3DCCJGgHYvxkkYid7NCI_GUS_KUcxhVEMjOelErNB3bsatvG4LW6n0ZsRC4K02qpuKqpZtmrQTNMYJA3QRAs7PTQQxS40eMCt3mX3duxnWb-
lS5h7nTI0A4jMWoo4c44P_Hku-zrOazdy64chWo-
ScfRkRgl8wgHKrLTH1OxHZkHgoHaTraHcopXUFYzPPVfuC_hwQaD1GrskdiNCdQwJljJqlvXfyqVsA5CGg0uRUQifHw56xFtciO75QrP07vo_JXf_tf8yK2ezDKY_ZWt_1y2qqYzv7bI1IW1V_sN19m-07wCAAA=))...
counter.count += 1}>
increment
...though note that if you _reassign_ `counter` instead of updating it, you
will ‘break the link’ — in other words instead of this...
counter = { count: 0 }}>
reset
...you must do this:
counter.count = 0}>
reset
Svelte will warn you if you get it wrong.
## Type-safe context
A useful pattern is to wrap the calls to `setContext` and `getContext` inside
helper functions that let you preserve type safety:
context
import { getContext, setContext } from 'svelte';
const key = {};
/** @param {User} user */
export function setUserContext(user) {
setContext(key, user);
}
export function getUserContext() {
return /** @type {User} */ (getContext(key));
}
import { getContext, setContext } from 'svelte';
const key = {};
export function setUserContext(user: User) {
setContext(key, user);
}
export function getUserContext() {
return getContext(key) as User;
}
## Replacing global state
When you have state shared by many different components, you might be tempted
to put it in its own module and just import it wherever it’s needed:
state.svelte
export const myGlobalState = $state({
user: {
// ...
}
// ...
});
In many cases this is perfectly fine, but there is a risk: if you mutate the
state during server-side rendering (which is discouraged, but entirely
possible!)...
App
...then the data may be accessible by the _next_ user. Context solves this
problem because it is not shared between requests.
# Custom elements
### On this page
* [Custom elements](custom-elements)
* Component lifecycle
* Component options
* Caveats and limitations
Svelte components can also be compiled to custom elements (aka web components)
using the `customElement: true` compiler option. You should specify a tag name
for the component using the `` [element](svelte-options).
Hello {name}!
You can leave out the tag name for any of your inner components which you
don’t want to expose and use them like regular Svelte components. Consumers of
the component can still name it afterwards if needed, using the static
`element` property which contains the custom element constructor and which is
available when the `customElement` compiler option is `true`.
import MyElement from './MyElement.svelte';
customElements.define('my-element', MyElement.element);
Once a custom element has been defined, it can be used as a regular DOM
element:
document.body.innerHTML = `
This is some slotted content
`;
Any [props](basic-markup#Component-props) are exposed as properties of the DOM
element (as well as being readable/writable as attributes, where possible).
const el = document.querySelector('my-element');
// get the current value of the 'name' prop
console.log(el.name);
// set a new value, updating the shadow DOM
el.name = 'everybody';
Note that you need to list out all properties explicitly, i.e. doing `let
props = $props()` without declaring `props` in the component options means
that Svelte can’t know which props to expose as properties on the DOM element.
## Component lifecycle
Custom elements are created from Svelte components using a wrapper approach.
This means the inner Svelte component has no knowledge that it is a custom
element. The custom element wrapper takes care of handling its lifecycle
appropriately.
When a custom element is created, the Svelte component it wraps is _not_
created right away. It is only created in the next tick after the
`connectedCallback` is invoked. Properties assigned to the custom element
before it is inserted into the DOM are temporarily saved and then set on
component creation, so their values are not lost. The same does not work for
invoking exported functions on the custom element though, they are only
available after the element has mounted. If you need to invoke functions
before component creation, you can work around it by using the `extend`
option.
When a custom element written with Svelte is created or updated, the shadow
DOM will reflect the value in the next tick, not immediately. This way updates
can be batched, and DOM moves which temporarily (but synchronously) detach the
element from the DOM don’t lead to unmounting the inner component.
The inner Svelte component is destroyed in the next tick after the
`disconnectedCallback` is invoked.
## Component options
When constructing a custom element, you can tailor several aspects by defining
`customElement` as an object within `` since Svelte 4. This
object may contain the following properties:
* `tag: string`: an optional `tag` property for the custom element’s name. If set, a custom element with this tag name will be defined with the document’s `customElements` registry upon importing this component.
* `shadow`: an optional property that can be set to `"none"` to forgo shadow root creation. Note that styles are then no longer encapsulated, and you can’t use slots
* `props`: an optional property to modify certain details and behaviors of your component’s properties. It offers the following settings:
* `attribute: string`: To update a custom element’s prop, you have two alternatives: either set the property on the custom element’s reference as illustrated above or use an HTML attribute. For the latter, the default attribute name is the lowercase property name. Modify this by assigning `attribute: ""`.
* `reflect: boolean`: By default, updated prop values do not reflect back to the DOM. To enable this behavior, set `reflect: true`.
* `type: 'String' | 'Boolean' | 'Number' | 'Array' | 'Object'`: While converting an attribute value to a prop value and reflecting it back, the prop value is assumed to be a `String` by default. This may not always be accurate. For instance, for a number type, define it using `type: "Number"` You don’t need to list all properties, those not listed will use the default settings.
* `extend`: an optional property which expects a function as its argument. It is passed the custom element class generated by Svelte and expects you to return a custom element class. This comes in handy if you have very specific requirements to the life cycle of the custom element or want to enhance the class to for example use [ElementInternals](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals#examples) for better HTML form integration.
{
// Extend the class so we can let it participate in HTML forms
return class extends customElementConstructor {
static formAssociated = true;
constructor() {
super();
this.attachedInternals = this.attachInternals();
}
// Add the function here, not below in the component so that
// it's always available, not just when the inner Svelte component
// is mounted
randomIndex() {
this.elementIndex = Math.random();
}
};
}
}}
/>
...
> While Typescript is supported in the `extend` function, it is subject to
> limitations: you need to set `lang="ts"` on one of the scripts AND you can
> only use [erasable
> syntax](https://www.typescriptlang.org/tsconfig/#erasableSyntaxOnly) in it.
> They are not processed by script preprocessors.
## Caveats and limitations
Custom elements can be a useful way to package components for consumption in a
non-Svelte app, as they will work with vanilla HTML and JavaScript as well as
[most frameworks](https://custom-elements-everywhere.com/). There are,
however, some important differences to be aware of:
* Styles are _encapsulated_ , rather than merely _scoped_ (unless you set `shadow: "none"`). This means that any non-component styles (such as you might have in a `global.css` file) will not apply to the custom element, including styles with the `:global(...)` modifier
* Instead of being extracted out as a separate .css file, styles are inlined into the component as a JavaScript string
* Custom elements are not generally suitable for server-side rendering, as the shadow DOM is invisible until JavaScript loads
* In Svelte, slotted content renders _lazily_. In the DOM, it renders _eagerly_. In other words, it will always be created even if the component’s `` element is inside an `{#if ...}` block. Similarly, including a `` in an `{#each ...}` block will not cause the slotted content to be rendered multiple times
* The deprecated `let:` directive has no effect, because custom elements do not have a way to pass data to the parent component that fills the slot
* Polyfills are required to support older browsers
* You can use Svelte’s context feature between regular Svelte components within a custom element, but you can’t use them across custom elements. In other words, you can’t use `setContext` on a parent custom element and read that with `getContext` in a child custom element.
* Don’t declare properties or attributes starting with `on`, as their usage will be interpreted as an event listener. In other words, Svelte treats ` ` as `customElement.addEventListener('eworld', true)` (and not as `customElement.oneworld = true`)
# Custom properties
### On this page
* [Custom properties](custom-properties)
You can pass CSS custom properties — both static and dynamic — to components:
The above code essentially desugars to this:
For an SVG element, it would use `` instead:
Inside the component, we can read these custom properties (and provide
fallback values) using [`var(...)`](https://developer.mozilla.org/en-
US/docs/Web/CSS/Using_CSS_custom_properties):
You don’t _have_ to specify the values directly on the component; as long as
the custom properties are defined on a parent element, the component can use
them. It’s common to define custom properties on the `:root` element in a
global stylesheet so that they apply to your entire application.
> While the extra element will not affect layout, it _will_ affect any CSS
> selectors that (for example) use the `>` combinator to target an element
> directly inside the component’s container.
# {#each ...}
### On this page
* [{#each ...}](each)
* Keyed each blocks
* Each blocks without an item
* Else blocks
{#each expression as name}...{/each}
{#each expression as name, index}...{/each}
Iterating over values can be done with an each block. The values in question
can be arrays, array-like objects (i.e. anything with a `length` property), or
iterables like `Map` and `Set` — in other words, anything that can be used
with `Array.from`.
Shopping list
{#each items as item}
{item.name} x {item.qty}
{/each}
An each block can also specify an _index_ , equivalent to the second argument
in an `array.map(...)` callback:
{#each items as item, i}
{i + 1}: {item.name} x {item.qty}
{/each}
## Keyed each blocks
{#each expression as name (key)}...{/each}
{#each expression as name, index (key)}...{/each}
If a _key_ expression is provided — which must uniquely identify each list
item — Svelte will use it to intelligently update the list when data changes
by inserting, moving and deleting items, rather than adding or removing items
at the end and updating the state in the middle.
The key can be any object, but strings and numbers are recommended since they
allow identity to persist when the objects themselves change.
{#each items as item (item.id)}
{item.name} x {item.qty}
{/each}
{#each items as item, i (item.id)}
{i + 1}: {item.name} x {item.qty}
{/each}
You can freely use destructuring and rest patterns in each blocks.
{#each items as { id, name, qty }, i (id)}
{i + 1}: {name} x {qty}
{/each}
{#each objects as { id, ...rest }}
{id}
{/each}
{#each items as [id, ...rest]}
{id}
{/each}
## Each blocks without an item
{#each expression}...{/each}
{#each expression, index}...{/each}
In case you just want to render something `n` times, you can omit the `as`
part
([demo](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE3WR0W7CMAxFf8XKNAk0WsSeUEaRpn3Guoc0MbQiJFHiMlDVf18SOrZJ48259_jaVgZmxBEZZ28thgCNFV6xBdt1GgPj7wOji0t2EqI-
wa_OleGEmpLWiID_6dIaQkMxhm1UdwKpRQhVzWSaVORJNdvWpqbhAYVsYQCNZk8thzWMC_DCHMZk3wPSThNQ088I3mghD9UwSwHwlLE5PMIzVFUFq3G7WUZ2OyUvU3JOuZU332wCXTRmtPy1NgzXZtUFp8WFw9536uWqpbIgPEaDsJBW90cTOHh0KGi2XsBq5-cT6-3nPauxXqHnsHJnCFZ3CvJVkyuCQ0mFF9TZyCQ162WGvteLKfG197Y3iv_pz_fmS68Hxt8iPBPj5HscP8YvCNX7uhYCAAA=)):
{#each { length: 8 }, rank}
{#each { length: 8 }, file}
{/each}
{/each}
## Else blocks
{#each expression as name}...{:else}...{/each}
An each block can also have an `{:else}` clause, which is rendered if the list
is empty.
{#each todos as todo}
{todo.text}
{:else}
No tasks today!
{/each}
# Frequently asked questions
### On this page
* [Frequently asked questions](faq)
* I’m new to Svelte. Where should I start?
* Where can I get support?
* Are there any third-party resources?
* How can I get VS Code to syntax-highlight my .svelte files?
* Is there a tool to automatically format my .svelte files?
* How do I document my components?
* Does Svelte scale?
* Is there a UI component library?
* How do I test Svelte apps?
* Is there a router?
* How do I write a mobile app with Svelte?
* Can I tell Svelte not to remove my unused styles?
* Is Svelte v2 still available?
* How do I do hot module reloading?
## I’m new to Svelte. Where should I start?
We think the best way to get started is playing through the interactive
[tutorial](https://svelte.dev/tutorial). Each step there is mainly focused on
one specific aspect and is easy to follow. You’ll be editing and running real
Svelte components right in your browser.
Five to ten minutes should be enough to get you up and running. An hour and a
half should get you through the entire tutorial.
## Where can I get support?
If your question is about certain syntax, the [reference
docs](https://svelte.dev/docs/svelte) are a good place to start.
Stack Overflow is a popular forum to ask code-level questions or if you’re
stuck with a specific error. Read through the existing questions tagged with
[Svelte](https://stackoverflow.com/questions/tagged/svelte+or+svelte-3) or
[ask your own](https://stackoverflow.com/questions/ask?tags=svelte)!
There are online forums and chats which are a great place for discussion about
best practices, application architecture or just to get to know fellow Svelte
users. [Our Discord](https://svelte.dev/chat) or [the Reddit
channel](https://www.reddit.com/r/sveltejs/) are examples of that. If you have
an answerable code-level question, Stack Overflow is usually a better fit.
## Are there any third-party resources?
Svelte Society maintains a [list of books and
videos](https://sveltesociety.dev/resources).
## How can I get VS Code to syntax-highlight my .svelte files?
There is an [official VS Code extension for
Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-
vscode).
## Is there a tool to automatically format my .svelte files?
You can use prettier with the [prettier-plugin-
svelte](https://www.npmjs.com/package/prettier-plugin-svelte) plugin.
## How do I document my components?
In editors which use the Svelte Language Server you can document Components,
functions and exports using specially formatted comments.
Hello, {name}
Note: The `@component` is necessary in the HTML comment which describes your
component.
## Does Svelte scale?
There will be a blog post about this eventually, but in the meantime, check
out [this issue](https://github.com/sveltejs/svelte/issues/2546).
## Is there a UI component library?
There are several UI component libraries as well as standalone components.
Find them under the [design systems section of the components
page](https://sveltesociety.dev/packages?category=design-system) on the Svelte
Society website.
## How do I test Svelte apps?
How your application is structured and where logic is defined will determine
the best way to ensure it is properly tested. It is important to note that not
all logic belongs within a component - this includes concerns such as data
transformation, cross-component state management, and logging, among others.
Remember that the Svelte library has its own test suite, so you do not need to
write tests to validate implementation details provided by Svelte.
A Svelte application will typically have three different types of tests: Unit,
Component, and End-to-End (E2E).
_Unit Tests_ : Focus on testing business logic in isolation. Often this is
validating individual functions and edge cases. By minimizing the surface area
of these tests they can be kept lean and fast, and by extracting as much logic
as possible from your Svelte components more of your application can be
covered using them. When creating a new SvelteKit project, you will be asked
whether you would like to setup [Vitest](https://vitest.dev/) for unit
testing. There are a number of other test runners that could be used as well.
_Component Tests_ : Validating that a Svelte component mounts and interacts as
expected throughout its lifecycle requires a tool that provides a Document
Object Model (DOM). Components can be compiled (since Svelte is a compiler and
not a normal library) and mounted to allow asserting against element
structure, listeners, state, and all the other capabilities provided by a
Svelte component. Tools for component testing range from an in-memory
implementation like jsdom paired with a test runner like
[Vitest](https://vitest.dev/) to solutions that leverage an actual browser to
provide a visual testing capability such as
[Playwright](https://playwright.dev/docs/test-components) or
[Cypress](https://www.cypress.io/).
_End-to-End Tests_ : To ensure your users are able to interact with your
application it is necessary to test it as a whole in a manner as close to
production as possible. This is done by writing end-to-end (E2E) tests which
load and interact with a deployed version of your application in order to
simulate how the user will interact with your application. When creating a new
SvelteKit project, you will be asked whether you would like to setup
[Playwright](https://playwright.dev/) for end-to-end testing. There are many
other E2E test libraries available for use as well.
Some resources for getting started with testing:
* [Svelte docs on testing](testing)
* [Setup Vitest using the Svelte CLI](https://svelte.dev/docs/cli/vitest)
* [Svelte Testing Library](https://testing-library.com/docs/svelte-testing-library/example/)
* [Svelte Component Testing in Cypress](https://docs.cypress.io/guides/component-testing/svelte/overview)
* [Example using uvu test runner with JSDOM](https://github.com/lukeed/uvu/tree/master/examples/svelte)
* [Test Svelte components using Vitest & Playwright](https://davipon.hashnode.dev/test-svelte-component-using-vitest-playwright)
* [Component testing with WebdriverIO](https://webdriver.io/docs/component-testing/svelte)
## Is there a router?
The official routing library is [SvelteKit](https://svelte.dev/docs/kit).
SvelteKit provides a filesystem router, server-side rendering (SSR), and hot
module reloading (HMR) in one easy-to-use package. It shares similarities with
Next.js for React.
However, you can use any router library. A lot of people use
[page.js](https://github.com/visionmedia/page.js). There’s also
[navaid](https://github.com/lukeed/navaid), which is very similar. And
[universal-router](https://github.com/kriasoft/universal-router), which is
isomorphic with child routes, but without built-in history support.
If you prefer a declarative HTML approach, there’s the isomorphic [svelte-
routing](https://github.com/EmilTholin/svelte-routing) library and a fork of
it called [svelte-navigator](https://github.com/mefechoel/svelte-navigator)
containing some additional functionality.
If you need hash-based routing on the client side, check out the [hash
option](https://svelte.dev/docs/kit/configuration#router) in SvelteKit,
[svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router), or
[abstract-state-router](https://github.com/TehShrike/abstract-state-router/).
[Routify](https://routify.dev) is another filesystem-based router, similar to
SvelteKit’s router. Version 3 supports Svelte’s native SSR.
You can see a [community-maintained list of routers on
sveltesociety.dev](https://sveltesociety.dev/packages?category=routers).
## How do I write a mobile app with Svelte?
While most mobile apps are written without using JavaScript, if you’d like to
leverage your existing Svelte components and knowledge of Svelte when building
mobile apps, you can turn a [SvelteKit
SPA](https://kit.svelte.dev/docs/single-page-apps) into a mobile app with
[Tauri](https://v2.tauri.app/start/frontend/sveltekit/) or
[Capacitor](https://capacitorjs.com/solution/svelte). Mobile features like the
camera, geolocation, and push notifications are available via plugins for both
platforms.
Svelte Native was an option available for Svelte 4, but note that Svelte 5
does not currently support it. Svelte Native lets you write NativeScript apps
using Svelte components that contain [NativeScript UI
components](https://docs.nativescript.org/ui/) rather than DOM elements, which
may be familiar for users coming from React Native.
## Can I tell Svelte not to remove my unused styles?
No. Svelte removes the styles from the component and warns you about them in
order to prevent issues that would otherwise arise.
Svelte’s component style scoping works by generating a class unique to the
given component, adding it to the relevant elements in the component that are
under Svelte’s control, and then adding it to each of the selectors in that
component’s styles. When the compiler can’t see what elements a style selector
applies to, there would be two bad options for keeping it:
* If it keeps the selector and adds the scoping class to it, the selector will likely not match the expected elements in the component, and they definitely won’t if they were created by a child component or `{@html ...}`.
* If it keeps the selector without adding the scoping class to it, the given style will become a global style, affecting your entire page.
If you need to style something that Svelte can’t identify at compile time, you
will need to explicitly opt into global styles by using `:global(...)`. But
also keep in mind that you can wrap `:global(...)` around only part of a
selector. `.foo :global(.bar) { ... }` will style any `.bar` elements that
appear within the component’s `.foo` elements. As long as there’s some parent
element in the current component to start from, partially global selectors
like this will almost always be able to get you what you want.
## Is Svelte v2 still available?
New features aren’t being added to it, and bugs will probably only be fixed if
they are extremely nasty or present some sort of security vulnerability.
The documentation is still available [here](https://v2.svelte.dev/guide).
## How do I do hot module reloading?
We recommend using [SvelteKit](https://svelte.dev/docs/kit), which supports
HMR out of the box and is built on top of [Vite](https://vitejs.dev/) and
[svelte-hmr](https://github.com/sveltejs/svelte-hmr). There are also community
plugins for [rollup](https://github.com/rixo/rollup-plugin-svelte-hot) and
[webpack](https://github.com/sveltejs/svelte-loader).
# Getting started
### On this page
* [Getting started](getting-started)
* Alternatives to SvelteKit
* Editor tooling
* Getting help
We recommend using [SvelteKit](https://svelte.dev/docs/kit), which lets you
[build almost anything](https://svelte.dev/docs/kit/project-types). It’s the
official application framework from the Svelte team and powered by
[Vite](https://vite.dev/). Create a new project with:
npx sv create myapp
cd myapp
npm install
npm run dev
Don’t worry if you don’t know Svelte yet! You can ignore all the nice features
SvelteKit brings on top for now and dive into it later.
## Alternatives to SvelteKit
You can also use Svelte directly with Vite by running `npm create vite@latest`
and selecting the `svelte` option. With this, `npm run build` will generate
HTML, JS, and CSS files inside the `dist` directory using [vite-plugin-
svelte](https://github.com/sveltejs/vite-plugin-svelte). In most cases, you
will probably need to [choose a routing library](faq#Is-there-a-router) as
well.
> Vite is often used in standalone mode to build [single page apps
> (SPAs)](https://svelte.dev/docs/kit/glossary#SPA), which you can also [build
> with SvelteKit](https://svelte.dev/docs/kit/single-page-apps).
There are also plugins for [Rollup](https://github.com/sveltejs/rollup-plugin-
svelte), [Webpack](https://github.com/sveltejs/svelte-loader) [and a few
others](https://sveltesociety.dev/packages?category=build-plugins), but we
recommend Vite.
## Editor tooling
The Svelte team maintains a [VS Code
extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-
vscode), and there are integrations with various other
[editors](https://sveltesociety.dev/resources#editor-support) and tools as
well.
You can also check your code from the command line using [sv
check](https://github.com/sveltejs/cli).
## Getting help
Don’t be shy about asking for help in the [Discord
chatroom](https://svelte.dev/chat)! You can also find answers on [Stack
Overflow](https://stackoverflow.com/questions/tagged/svelte).
# Global styles
### On this page
* [Global styles](global-styles)
* :global(...)
* :global
## :global(...)
To apply styles to a single selector globally, use the `:global(...)`
modifier:
If you want to make @keyframes that are accessible globally, you need to
prepend your keyframe names with `-global-`.
The `-global-` part will be removed when compiled, and the keyframe will then
be referenced using just `my-animation-name` elsewhere in your code.
## :global
To apply styles to a group of selectors globally, create a `:global {...}`
block:
> The second example above could also be written as an equivalent `.a :global
> .b .c .d` selector, where everything after the `:global` is unscoped, though
> the nested form is preferred.
# {#if ...}
### On this page
* [{#if ...}](if)
{#if expression}...{/if}
{#if expression}...{:else if expression}...{/if}
{#if expression}...{:else}...{/if}
Content that is conditionally rendered can be wrapped in an if block.
{#if answer === 42}
what was the question?
{/if}
Additional conditions can be added with `{:else if expression}`, optionally
ending in an `{:else}` clause.
{#if porridge.temperature > 100}
too hot!
{:else if 80 > porridge.temperature}
too cold!
{:else}
just right!
{/if}
(Blocks don’t have to wrap elements, they can also wrap text within elements.)
# Imperative component API
### On this page
* [Imperative component API](imperative-component-api)
* mount
* unmount
* render
* hydrate
Every Svelte application starts by imperatively creating a root component. On
the client this component is mounted to a specific element. On the server, you
want to get back a string of HTML instead which you can render. The following
functions help you achieve those tasks.
## mount
Instantiates a component and mounts it to the given target:
import { mount } from 'svelte';
import App from './App.svelte';
const app = mount(App, {
target: document.querySelector('#app'),
props: { some: 'property' }
});
You can mount multiple components per page, and you can also mount from within
your application, for example when creating a tooltip component and attaching
it to the hovered element.
Note that unlike calling `new App(...)` in Svelte 4, things like effects
(including `onMount` callbacks, and action functions) will not run during
`mount`. If you need to force pending effects to run (in the context of a
test, for example) you can do so with `flushSync()`.
## unmount
Unmounts a component that was previously created with `mount` or `hydrate`.
If `options.outro` is `true`, [transitions](transition) will play before the
component is removed from the DOM:
import { mount, unmount } from 'svelte';
import App from './App.svelte';
const app = mount(App, { target: document.body });
// later
unmount(app, { outro: true });
Returns a `Promise` that resolves after transitions have completed if
`options.outro` is true, or immediately otherwise.
## render
Only available on the server and when compiling with the `server` option.
Takes a component and returns an object with `body` and `head` properties on
it, which you can use to populate the HTML when server-rendering your app:
import { render } from 'svelte/server';
import App from './App.svelte';
const result = render(App, {
props: { some: 'property' }
});
result.body; // HTML for somewhere in this tag
result.head; // HTML for somewhere in this tag
## hydrate
Like `mount`, but will reuse up any HTML rendered by Svelte’s SSR output (from
the `render` function) inside the target and make it interactive:
import { hydrate } from 'svelte';
import App from './App.svelte';
const app = hydrate(App, {
target: document.querySelector('#app'),
props: { some: 'property' }
});
As with `mount`, effects will not run during `hydrate` — use `flushSync()`
immediately afterwards if you need them to.
# in: and out:
### On this page
* [in: and out:](in-and-out)
The `in:` and `out:` directives are identical to [`transition:`](transition),
except that the resulting transitions are not bidirectional — an `in`
transition will continue to ‘play’ alongside the `out` transition, rather than
reversing, if the block is outroed while the transition is in progress. If an
out transition is aborted, transitions will restart from scratch.
visible
{#if visible}
flies in, fades out
{/if}
# Svelte
### On this page
* [Overview](overview)
Svelte is a framework for building user interfaces on the web. It uses a
compiler to turn declarative components written in HTML, CSS and JavaScript...
App
click me
click me
...into lean, tightly optimized JavaScript.
You can use it to build anything on the web, from standalone components to
ambitious full stack apps (using Svelte’s companion application framework,
[SvelteKit](https://svelte.dev/docs/kit)) and everything in between.
These pages serve as reference documentation. If you’re new to Svelte, we
recommend starting with the [interactive
tutorial](https://svelte.dev/tutorial) and coming back here when you have
questions.
You can also try Svelte online in the
[playground](https://svelte.dev/playground) or, if you need a more fully-
featured environment, on [StackBlitz](https://sveltekit.new).
# {#key ...}
### On this page
* [{#key ...}](key)
{#key expression}...{/key}
Key blocks destroy and recreate their contents when the value of an expression
changes. When used around components, this will cause them to be
reinstantiated and reinitialised:
{#key value}
{/key}
It’s also useful if you want a transition to play whenever a value changes:
{#key value}
{value}
{/key}
# $$props and $$restProps
### On this page
* [$$props and $$restProps](legacy-$$props-and-$$restprops)
In runes mode, getting an object containing all the props that were passed in
is easy, using the [`$props`]($props) rune.
In legacy mode, we use `$$props` and `$$restProps`:
* `$$props` contains all the props that were passed in, including ones that are not individually declared with the `export` keyword
* `$$restProps` contains all the props that were passed in _except_ the ones that were individually declared
For example, a `` component might need to pass along all its props to
its own `` element, except the `variant` prop:
click me
In Svelte 3/4 using `$$props` and `$$restProps` creates a modest performance
penalty, so they should only be used when needed.
# $$slots
### On this page
* [$$slots](legacy-$$slots)
In runes mode, we know which [snippets](snippet) were provided to a component,
as they’re just normal props.
In legacy mode, the way to know if content was provided for a given slot is
with the `$$slots` object, whose keys are the names of the slots passed into
the component by the parent.
Card
{#if $$slots.description}
{/if}
App
Blog Post Title
# Imperative component API
### On this page
* [Imperative component API](legacy-component-api)
* Creating a component
* $set
* $on
* $destroy
* Component props
* Server-side component API
In Svelte 3 and 4, the API for interacting with a component is different than
in Svelte 5. Note that this page does _not_ apply to legacy mode components in
a Svelte 5 application.
## Creating a component
const component = new Component(options);
A client-side component — that is, a component compiled with `generate: 'dom'`
(or the `generate` option left unspecified) is a JavaScript class.
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
// assuming App.svelte contains something like
// `export let answer`:
answer: 42
}
});
The following initialisation options can be provided:
option | default | description
---|---|---
`target` | **none** | An `HTMLElement` or `ShadowRoot` to render to. This option is required
`anchor` | `null` | A child of `target` to render the component immediately before
`props` | `{}` | An object of properties to supply to the component
`context` | `new Map()` | A `Map` of root-level context key-value pairs to supply to the component
`hydrate` | `false` | See below
`intro` | `false` | If `true`, will play transitions on initial render, rather than waiting for subsequent state changes
Existing children of `target` are left where they are.
The `hydrate` option instructs Svelte to upgrade existing DOM (usually from
server-side rendering) rather than creating new elements. It will only work if
the component was compiled with the [`hydratable: true`
option](https://svelte.dev/docs/svelte-compiler#compile). Hydration of
`` elements only works properly if the server-side rendering code was
also compiled with `hydratable: true`, which adds a marker to each element in
the `` so that the component knows which elements it’s responsible for
removing during hydration.
Whereas children of `target` are normally left alone, `hydrate: true` will
cause any children to be removed. For that reason, the `anchor` option cannot
be used alongside `hydrate: true`.
The existing DOM doesn’t need to match the component — Svelte will ‘repair’
the DOM as it goes.
index
import App from './App.svelte';
const app = new App({
target: document.querySelector('#server-rendered-html'),
hydrate: true
});
> In Svelte 5+, use [`mount`](svelte#mount) instead
## $set
component.$set(props);
Programmatically sets props on an instance. `component.$set({ x: 1 })` is
equivalent to `x = 1` inside the component’s `
The default value is used if it would otherwise be `undefined` when the
component is created.
> Unlike in runes mode, if the parent component changes a prop from a defined
> value to `undefined`, it does not revert to the initial value.
Props without default values are considered _required_ , and Svelte will print
a warning during development if no value is provided, which you can squelch by
specifying `undefined` as the default value:
export let foo = undefined;
## Component exports
An exported `const`, `class` or `function` declaration is _not_ considered a
prop — instead, it becomes part of the component’s API:
Greeter
App
greeter.greet('world')}>
greet
greeter.greet('world')}>
greet
## Renaming props
The `export` keyword can appear separately from the declaration. This is
useful for renaming props, for example in the case of a reserved word:
App
# Reactive let/var declarations
### On this page
* [Reactive let/var declarations](legacy-let)
In runes mode, reactive state is explicitly declared with the [`$state`
rune]($state).
In legacy mode, variables declared at the top level of a component are
automatically considered _reactive_. Reassigning or mutating these variables
(`count += 1` or `object.x = y`) will cause the UI to update.
count += 1}>
clicks: {count}
Because Svelte’s legacy mode reactivity is based on _assignments_ , using
array methods like `.push()` and `.splice()` won’t automatically trigger
updates. A subsequent assignment is required to ‘tell’ the compiler to update
the UI:
# on:
### On this page
* [on:](legacy-on)
* Component events
In runes mode, event handlers are just like any other attribute or prop.
In legacy mode, we use the `on:` directive:
App
count: {count}
count: {count}
Handlers can be declared inline with no performance penalty:
(count += 1)}>
count: {count}
Add _modifiers_ to element event handlers with the `|` character.
The following modifiers are available:
* `preventDefault` — calls `event.preventDefault()` before running the handler
* `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element
* `stopImmediatePropagation` \- calls `event.stopImmediatePropagation()`, preventing other listeners of the same event from being fired.
* `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it’s safe to do so)
* `nonpassive` — explicitly set `passive: false`
* `capture` — fires the handler during the _capture_ phase instead of the _bubbling_ phase
* `once` — remove the handler after the first time it runs
* `self` — only trigger handler if `event.target` is the element itself
* `trusted` — only trigger handler if `event.isTrusted` is `true`. I.e. if the event is triggered by a user action.
Modifiers can be chained together, e.g. `on:click|once|capture={...}`.
If the `on:` directive is used without a value, the component will _forward_
the event, meaning that a consumer of the component can listen for it.
The component itself will emit the click event
It’s possible to have multiple event listeners for the same event:
App
clicks: {count}
clicks: {count}
## Component events
Components can dispatch events by creating a _dispatcher_ when they are
initialised:
Stepper
dispatch('decrement')}>decrement
dispatch('increment')}>increment
dispatch('decrement')}>decrement
dispatch('increment')}>increment
`dispatch` creates a [`CustomEvent`](https://developer.mozilla.org/en-
US/docs/Web/API/CustomEvent). If a second argument is provided, it becomes the
`detail` property of the event object.
A consumer of this component can listen for the dispatched events:
n -= 1}
on:increment={() => n += 1}
/>
n: {n}
Component events do not bubble — a parent component can only listen for events
on its immediate children.
Other than `once`, modifiers are not valid on component event handlers.
> If you’re planning an eventual migration to Svelte 5, use callback props
> instead. This will make upgrading easier as `createEventDispatcher` is
> deprecated:
>
> Stepper
>
>
>
>
> decrement
> increment
>
>
>
>
> decrement
> increment
# Overview
### On this page
* [Overview](legacy-overview)
Svelte 5 introduced some significant changes to Svelte’s API, including
[runes](what-are-runes), [snippets](snippet) and event attributes. As a
result, some Svelte 3/4 features are deprecated (though supported for now,
unless otherwise specified) and will eventually be removed. We recommend that
you incrementally [migrate your existing code](v5-migration-guide).
The following pages document these features for
* people still using Svelte 3/4
* people using Svelte 5, but with components that haven’t yet been migrated
Since Svelte 3/4 syntax still works in Svelte 5, we will distinguish between
_legacy mode_ and _runes mode_. Once a component is in runes mode (which you
can opt into by using runes, or by explicitly setting the `runes: true`
compiler option), legacy mode features are no longer available.
If you’re exclusively interested in the Svelte 3/4 syntax, you can browse its
documentation at [v4.svelte.dev](https://v4.svelte.dev).
# Reactive $: statements
### On this page
* [Reactive $: statements](legacy-reactive-assignments)
* Understanding dependencies
* Browser-only code
In runes mode, reactions to state updates are handled with the
[`$derived`]($derived) and [`$effect`]($effect) runes.
In legacy mode, any top-level statement (i.e. not inside a block or a
function) can be made reactive by prefixing it with a `$:`
[label](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/label). These statements run after
other code in the `
Statements are ordered _topologically_ by their dependencies and their
assignments: since the `console.log` statement depends on `sum`, `sum` is
calculated first even though it appears later in the source.
Multiple statements can be combined by putting them in a block:
$: {
// recalculate `total` when `items` changes
total = 0;
for (const item of items) {
total += item.value;
}
}
The left-hand side of a reactive assignments can be an identifier, or it can
be a destructuring assignment:
$: ({ larry, moe, curly } = stooges);
## Understanding dependencies
The dependencies of a `$:` statement are determined at compile time — they are
whichever variables are referenced (but not assigned to) inside the statement.
In other words, a statement like this will _not_ re-run when `count` changes,
because the compiler cannot ‘see’ the dependency:
let count = 0;
let double = () => count * 2;
$: doubled = double();
Similarly, topological ordering will fail if dependencies are referenced
indirectly: `z` will never update, because `y` is not considered ‘dirty’ when
the update occurs. Moving `$: z = y` below `$: setY(x)` will fix it:
## Browser-only code
Reactive statements run during server-side rendering as well as in the
browser. This means that any code that should only run in the browser must be
wrapped in an `if` block:
$: if (browser) {
document.title = title;
}
#
### On this page
* [](legacy-slots)
* Named slots
* Fallback content
* Passing data to slotted content
In Svelte 5, content can be passed to components in the form of
[snippets](snippet) and rendered using [render tags](@render).
In legacy mode, content inside component tags is considered _slotted content_
, which can be rendered by the component using a `` element:
App
This is some slotted content
This is some slotted content
Modal
> If you want to render a regular `` element, you can use
> ` `.
## Named slots
A component can have _named_ slots in addition to the default slot. On the
parent side, add a `slot="..."` attribute to an element, component or
[``](legacy-svelte-fragment) directly inside the component
tags.
App
{#if open}
This is some slotted content
open = false}>
close
{/if}
{#if open}
This is some slotted content
open = false}>
close
{/if}
On the child side, add a corresponding `` element:
Modal
## Fallback content
If no slotted content is provided, a component can define fallback content by
putting it inside the `` element:
This will be rendered if no slotted content is provided
## Passing data to slotted content
Slots can be rendered zero or more times and can pass values _back_ to the
parent using props. The parent exposes the values to the slot template using
the `let:` directive.
FancyList
{#each items as data}
{/each}
App
{processed.text}
The usual shorthand rules apply — `let:item` is equivalent to
`let:item={item}`, and `` is equivalent to ``.
Named slots can also expose values. The `let:` directive goes on the element
with the `slot` attribute.
FancyList
{#each items as item}
{/each}
App
{item.text}
Copyright (c) 2019 Svelte Industries
#
### On this page
* [](legacy-svelte-component)
In runes mode, `` will re-render if the value of `MyComponent`
changes. See the [Svelte 5 migration guide](v5-migration-
guide#svelte:component-is-no-longer-necessary) for an example.
In legacy mode, it won’t — we must use ``, which destroys
and recreates the component instance when the value of its `this` expression
changes:
If `this` is falsy, no component is rendered.
#
### On this page
* [](legacy-svelte-fragment)
The `` element allows you to place content in a [named
slot](legacy-slots) without wrapping it in a container DOM element. This keeps
the flow layout of your document intact.
Widget
No header was provided
Some content between header and footer
App
Hello
All rights reserved.
Copyright (c) 2019 Svelte Industries
Hello
All rights reserved.
Copyright (c) 2019 Svelte Industries
> In Svelte 5+, this concept is obsolete, as snippets don’t create a wrapping
> element
#
### On this page
* [](legacy-svelte-self)
The `` element allows a component to include itself, recursively.
It cannot appear at the top level of your markup; it must be inside an if or
each block or passed to a component’s slot to prevent an infinite loop.
{#if count > 0}
counting down... {count}
{:else}
lift-off!
{/if}
> This concept is obsolete, as components can import themselves:
>
> App
>
>
>
>
> {#if count > 0}
> counting down... {count}
>
> {:else}
> lift-off!
> {/if}
>
>
>
>
> {#if count > 0}
> counting down... {count}
>
> {:else}
> lift-off!
> {/if}
# Lifecycle hooks
### On this page
* [Lifecycle hooks](lifecycle-hooks)
* onMount
* onDestroy
* tick
* Deprecated: beforeUpdate / afterUpdate
In Svelte 5, the component lifecycle consists of only two parts: Its creation
and its destruction. Everything in-between — when certain state is updated —
is not related to the component as a whole; only the parts that need to react
to the state change are notified. This is because under the hood the smallest
unit of change is actually not a component, it’s the (render) effects that the
component sets up upon component initialization. Consequently, there’s no such
thing as a “before update”/"after update” hook.
## onMount
The `onMount` function schedules a callback to run as soon as the component
has been mounted to the DOM. It must be called during the component’s
initialisation (but doesn’t need to live _inside_ the component; it can be
called from an external module).
`onMount` does not run inside a component that is rendered on the server.
If a function is returned from `onMount`, it will be called when the component
is unmounted.
> This behaviour will only work when the function passed to `onMount`
> _synchronously_ returns a value. `async` functions always return a
> `Promise`, and as such cannot _synchronously_ return a function.
## onDestroy
Schedules a callback to run immediately before the component is unmounted.
Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the
only one that runs inside a server-side component.
## tick
While there’s no “after update” hook, you can use `tick` to ensure that the UI
is updated before continuing. `tick` returns a promise that resolves once any
pending state changes have been applied, or in the next microtask if there are
none.
## Deprecated: beforeUpdate / afterUpdate
Svelte 4 contained hooks that ran before and after the component as a whole
was updated. For backwards compatibility, these hooks were shimmed in Svelte 5
but not available inside components that use runes.
Instead of `beforeUpdate` use `$effect.pre` and instead of `afterUpdate` use
`$effect` instead - these runes offer more granular control and only react to
the changes you’re actually interested in.
### Chat window example
To implement a chat window that autoscrolls to the bottom when new messages
appear (but only if you were _already_ scrolled to the bottom), we need to
measure the DOM before we update it.
In Svelte 4, we do this with `beforeUpdate`, but this is a flawed approach —
it fires before _every_ update, whether it’s relevant or not. In the example
below, we need to introduce checks like `updatingMessages` to make sure we
don’t mess with the scroll position when someone toggles dark mode.
With runes, we can use `$effect.pre`, which behaves the same as `$effect` but
runs before the DOM is updated. As long as we explicitly reference `messages`
inside the effect body, it will run whenever `messages` changes, but _not_
when `theme` changes.
`beforeUpdate`, and its equally troublesome counterpart `afterUpdate`, are
therefore deprecated in Svelte 5.
* [Before](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE31WXa_bNgz9K6yL1QmWOLlrC-w6H8MeBgwY9tY9NfdBtmlbiywZkpyPBfnvo2zLcZK28AWuRPGI5OGhkEuQc4EmiL9eAskqDOLg97oOZoE9125jDigs0t6oRqfOsjap5rXd7uTO8qpW2sIFEsyVxn_qjFmcAcstar-xPN3DFXKtKgi768IVgQku0ELj3Lgs_kZjWIEGNpAzYXDlHWyJFZI1zJjeh4O5uvl_DY8oUkVeVoFuJKYls-_CGYS25Aboj0EtWNqel0wWoBoLTGZgmdgDS9zW4Uz4NsrswPHoyutN4xInkylstnBxdmIhh8m7xzqmoNE2Wq46n1RJQzEbq4g-JQSl7e-HDx-GdaTy3KD9E3lRWvj5Zu9QX1QN20dj7zyHz8s-1S6lW7Cpz3RnXTcm04hIlfdFuO8p2mQ5-3a06cqjrn559bF_2NHOnRZ5I1PLlXQNyQT-hedMHeUEDyjtdMxsa4n2eIbNhlTwhyRthaOKOmYtniwF6pwt0wXa6MBEg0OibZec27gz_dk3UrZ6hB2LLYoiv521Yd8Gt-foTrfhiCDP0lC9VUUhcDLU49Xe_9943cNvEArHfAjxeBTovvXiNpFynfEDpIIZs9kFbg52QbeNHWZzebz32s7xHco3nJAJl1nshmhz8dYOQJDyZetnbb2gTWe-vEeWlrfpZMavr56ldb29eNt6UXvgwgFbp_WC0tl2RK25rGk6lYz3nUI2lzvBXGHhPZPGWmKUXFNBKqdaW259wl_aHbiqoVIZdpE60Nax6IOujT0LbFFxIVTCxCRR2XloUcYNvSbnGHKBp763jHoj59xiZWJI0Wm0P_m3MSS985xkasn-cFq20xTDy3J5KFcjgUTD69BHdcHIjz431z28IqlxGcPSfdFnrGDZn6gD6lyo45zyHAD-btczf-98nhQxHEvKfeUtOVkSejD3q-9X7JbzjGtsdUxlKdFU8qGsT78uaw848syWMXz85Waq2Gnem4mAn3prweq4q6Y3JEpnqMmnPoFRgmd3ySW0LLRqSKlwYHriCvJvUs2yjMaaoA-XzTXLeGMe45zmhv_XAno3Mj0xF7USuqNvnE9H343QHlq-eAgxpbTPNR9yzUkgLjwSR0NK4wKoxy-jDg-9vy8sUSToakzW-9fX13Em9Q8T6Z26uZhBN36XUYo5q7ggLXBZoub2Ofv7g6GCZfTxe034NCjiudXj7Omla0eTfo7QBPOcYxbE7qG-vl3_B1G-_i_JCAAA)
* [After](https://svelte.dev/playground/untitled#H4sIAAAAAAAAE31WXa-jNhD9K7PsdknUQJLurtRLPqo-VKrU1327uQ8GBnBjbGSb5KZR_nvHgMlXtyIS9njO-MyZGZRzUHCBJkhez4FkNQZJ8HvTBLPAnhq3MQcUFmlvVKszZ1mbTPPGbndyZ3ndKG3hDJZne7hAoVUNYY8JV-RBPgIt2AprhA18MpZZnIQ50_twuvLHNRrDSjRXj9fwiCJTBLIKdCsxq5j9EM4gtBU3QD8GjWBZd14xWYJqLTCZg2ViDyx1W4cz4dv0hsiB49FRHkyfsCgws3GjcTKZwmYLZ2feWc9o1W8zJQ2Fb62i5JUQRNRHgs-fx3WsisKg_RN5WVn4-WrvUd9VA9tH4-AcwbfFQIpkLWByvWzqSe2sk3kyjUlOec_XPU-3TRaz_75tuvKoi19e3OvipSpamVmupJM2F_gXnnJ1lBM8oLQjHceys8R7PMFms4HwD2lRhzeEe-EsvluSrHe2TJdo4wMTLY48XKwPzm0KGm2r5ajFtRYU4TWOY7-ddWHfxhDP0QkQhnf5PWRnVVkKnIx8fZsOb5dR16nwG4TCCRdCMphWQ7z1_DoOcp3zA2SCGbPZBa5jd0G_TRxmc36Me-mG6A7l60XIlMs8ce2-OXtrDyBItdz6qVjPadObzx-RZdV1nJjx64tXad1sz962njceOHfAzmk9JzrbXqg1lw3NkZL7vgE257t-uMDcO6attSSokpmgFqVMO2U93e_dDlzOUKsc-3t6zNZp6K9cG3sS2KGSUqiUiUmq8tNYoJwbmvpTAoXA96GyjCojI26xNglk6DpwOPm7NdRYp4ia0JL94bTqRiGB5WJxqFY37RGPoz3c6i4jP3rcUA7wmhqNywQW7om_YQ2L4UQdUBdCHSPiOQJ8bFcxHzeK0jKBY0XcV95SkCWlD9t-9eOM3TLKucauiyktJdpaPqT19ddF4wFHntsqgS-_XE01e48GMwnw02AtWZP02QyGVOkcNfk072CU4PkduZSWpVYt9SkcmJ64hPwHpWF5ziVls3wIFmmW89Y83vMeGf5PBxjcyPSkXNy10J18t3x6-a6CDtBq6SGklNKeazFyLahB3PVIGo2UbhOgGi9vKjzW_j6xVFFD17difXx5ebll0vwvkcGpn4sZ9MN3vqFYsJoL6gUuK9TcPrO_PxgzWMRfflSEr2NHPJf6lj1957rRpH8CNMG84JgHidUtXt4u_wK21LXERAgAAA==)
{#each messages as message}
{message}
{/each}
Toggle dark mode
# Nested
# Overview
### On this page
* [Overview](overview)
Svelte is a framework for building user interfaces on the web. It uses a
compiler to turn declarative components written in HTML, CSS and JavaScript...
App
click me
click me
...into lean, tightly optimized JavaScript.
You can use it to build anything on the web, from standalone components to
ambitious full stack apps (using Svelte’s companion application framework,
[SvelteKit](https://svelte.dev/docs/kit)) and everything in between.
These pages serve as reference documentation. If you’re new to Svelte, we
recommend starting with the [interactive
tutorial](https://svelte.dev/tutorial) and coming back here when you have
questions.
You can also try Svelte online in the
[playground](https://svelte.dev/playground) or, if you need a more fully-
featured environment, on [StackBlitz](https://sveltekit.new).
# Runtime errors
### On this page
* [Runtime errors](runtime-errors)
* Client errors
* Server errors
* Shared errors
## Client errors
### bind_invalid_checkbox_value
Using `bind:value` together with a checkbox input is not allowed. Use `bind:checked` instead
### bind_invalid_export
Component %component% has an export named `%key%` that a consumer component is trying to access using `bind:%key%`, which is disallowed. Instead, use `bind:this` (e.g. `<%name% bind:this={component} />`) and then access the property on the bound component instance (e.g. `component.%key%`)
### bind_not_bindable
A component is attempting to bind to a non-bindable property `%key%` belonging to %component% (i.e. `<%name% bind:%key%={...}>`). To mark a property as bindable: `let { %key% = $bindable() } = $props()`
### component_api_changed
Calling `%method%` on a component instance (of %component%) is no longer valid in Svelte 5
See the [migration guide](v5-migration-guide#Components-are-no-longer-classes)
for more information.
### component_api_invalid_new
Attempted to instantiate %component% with `new %name%`, which is no longer valid in Svelte 5. If this component is not under your control, set the `compatibility.componentApi` compiler option to `4` to keep it working.
See the [migration guide](v5-migration-guide#Components-are-no-longer-classes)
for more information.
### derived_references_self
A derived value cannot reference itself recursively
### each_key_duplicate
Keyed each block has duplicate key at indexes %a% and %b%
Keyed each block has duplicate key `%value%` at indexes %a% and %b%
### effect_in_teardown
`%rune%` cannot be used inside an effect cleanup function
### effect_in_unowned_derived
Effect cannot be created inside a `$derived` value that was not itself created inside an effect
### effect_orphan
`%rune%` can only be used inside an effect (e.g. during component initialisation)
### effect_update_depth_exceeded
Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops
### hydration_failed
Failed to hydrate the application
### invalid_snippet
Could not `{@render}` snippet due to the expression being `null` or `undefined`. Consider using optional chaining `{@render snippet?.()}`
### lifecycle_legacy_only
`%name%(...)` cannot be used in runes mode
### props_invalid_value
Cannot do `bind:%key%={undefined}` when `%key%` has a fallback value
### props_rest_readonly
Rest element properties of `$props()` such as `%property%` are readonly
### rune_outside_svelte
The `%rune%` rune is only available inside `.svelte` and `.svelte.js/ts` files
### state_descriptors_fixed
Property descriptors defined on `$state` objects must contain `value` and always be `enumerable`, `configurable` and `writable`.
### state_prototype_fixed
Cannot set prototype of `$state` object
### state_unsafe_mutation
Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
This error occurs when state is updated while evaluating a `$derived`. You
might encounter it while trying to ‘derive’ two pieces of state in one go:
count++}>{count}
{count} is even: {even}
{count} is odd: {odd}
This is forbidden because it introduces instability: if `{count} is even:
{even}
` is updated before `odd` is recalculated, `even` will be stale. In
most cases the solution is to make everything derived:
let even = $derived(count % 2 === 0);
let odd = $derived(!even);
If side-effects are unavoidable, use [`$effect`]($effect) instead.
## Server errors
### lifecycle_function_unavailable
`%name%(...)` is not available on the server
Certain methods such as `mount` cannot be invoked while running in a server
context. Avoid calling them eagerly, i.e. not during render.
## Shared errors
### invalid_default_snippet
Cannot use `{@render children(...)}` if the parent component uses `let:` directives. Consider using a named snippet instead
This error would be thrown in a setup like this:
Parent
{entry}
List
{#each items as item}
{@render children(item)}
{/each}
{#each items as item}
{@render children(item)}
{/each}
Here, `List.svelte` is using `{@render children(item)` which means it expects
`Parent.svelte` to use snippets. Instead, `Parent.svelte` uses the deprecated
`let:` directive. This combination of APIs is incompatible, hence the error.
### invalid_snippet_arguments
A snippet function was passed invalid arguments. Snippets should only be instantiated via `{@render ...}`
### lifecycle_outside_component
`%name%(...)` can only be used during component initialisation
Certain lifecycle methods can only be used during component initialisation. To
fix this, make sure you’re invoking the method inside the _top level of the
instance script_ of your component.
click me
### snippet_without_render_tag
Attempted to render a snippet without a `{@render}` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change `{snippet}` to `{@render snippet()}`.
A component throwing this error will look something like this (`children` is
not being rendered):
{children}
...or like this (a parent component is passing a snippet where a non-snippet
value is expected):
Parent
{#snippet label()}
Hi!
{/snippet}
Child
{label}
{label}
### store_invalid_shape
`%name%` is not a store with a `subscribe` method
### svelte_element_invalid_this_value
The `this` prop on `` must be a string, if defined
# Runtime warnings
### On this page
* [Runtime warnings](runtime-warnings)
* Client warnings
* Shared warnings
## Client warnings
### assignment_value_stale
Assignment to `%property%` property (%location%) will evaluate to the right-hand side, not the value of `%property%` following the assignment. This may result in unexpected behaviour.
Given a case like this...
add
items: {JSON.stringify(object.items)}
...the array being pushed to when the button is first clicked is the `[]` on
the right-hand side of the assignment, but the resulting value of
`object.array` is an empty state proxy. As a result, the pushed value will be
discarded.
You can fix this by separating it into two statements:
function add() {
object.array ??= [];
object.array.push(object.array.length);
}
### binding_property_non_reactive
`%binding%` is binding to a non-reactive property
`%binding%` (%location%) is binding to a non-reactive property
### console_log_state
Your `console.%method%` contained `$state` proxies. Consider using `$inspect(...)` or `$state.snapshot(...)` instead
When logging a [proxy](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Proxy), browser devtools will
log the proxy itself rather than the value it represents. In the case of
Svelte, the ‘target’ of a `$state` proxy might not resemble its current value,
which can be confusing.
The easiest way to log a value as it changes over time is to use the
[`$inspect`]($inspect) rune. Alternatively, to log things on a one-off basis
(for example, inside an event handler) you can use
[`$state.snapshot`]($state#$state.snapshot) to take a snapshot of the current
value.
### event_handler_invalid
%handler% should be a function. Did you mean to %suggestion%?
### hydration_attribute_changed
The `%attribute%` attribute on `%html%` changed its value between server and client renders. The client value, `%value%`, will be ignored in favour of the server value
Certain attributes like `src` on an ` ` element will not be repaired
during hydration, i.e. the server value will be kept. That’s because updating
these attributes can cause the image to be refetched (or in the case of an
`