Introduction
Runes
Template syntax
Styling
Special elements
Runtime
Misc
Reference
Legacy APIs
Compiler warnings
Svelte warns you at compile time if it catches potential mistakes, such as writing inaccessible markup.
Some warnings may be incorrect in your concrete use case. You can disable such false positives by placing a<!-- svelte-ignore <code> -->
comment above the line that causes the warning. Example:
<!-- svelte-ignore a11y_autofocus --><inputautofocus/>
You can list multiple rules in a single comment (separated by commas), and add an explanatory note (in parentheses) alongside them:
<!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_static_element_interactions (because of reasons) --><divonclick>...</div>
a11y_accesskey
Avoid using accesskey
Enforce noaccesskey
on element. Access keys are HTML attributes that allow web developers to assign keyboard shortcuts to elements. Inconsistencies between keyboard shortcuts and keyboard commands used by screen reader and keyboard-only users create accessibility complications. To avoid complications, access keys should not be used.
<!-- A11y: Avoid using accesskey --><divaccesskey="z"></div>
a11y_aria_activedescendant_has_tabindex
An element with an aria-activedescendant attribute should have a tabindex value
An element witharia-activedescendant
must be tabbable, so it must either have an inherenttabindex
or declaretabindex
as an attribute.
<!-- A11y: Elements with attribute aria-activedescendant should have tabindex value --><divaria-activedescendant="some-id"></div>
a11y_aria_attributes
`<%name%>` should not have aria-* attributes
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for examplemeta
,html
,script
,style
. This rule enforces that these DOM elements do not contain thearia-*
props.
<!-- A11y: <meta> should not have aria-* attributes --><metaaria-hidden="false"/>
a11y_autocomplete_valid
'%value%' is an invalid value for 'autocomplete' on `<input type="%type%">`
a11y_autofocus
Avoid using autofocus
Enforce thatautofocus
is not used on elements. Autofocusing elements can cause usability issues for sighted and non-sighted users alike.
<!-- A11y: Avoid using autofocus --><inputautofocus/>
a11y_click_events_have_key_events
Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as `<button type="button">` or `<a>` might be more appropriate
Enforce that visible, non-interactive elements with anonclick
event are accompanied by a keyboard event handler.
Users should first consider whether an interactive element might be more appropriate such as a<button type="button">
element for actions or<a>
element for navigations. These elements are more semantically meaningful and will have built-in key handling. E.g.Space
andEnter
will trigger a<button>
andEnter
will trigger an<a>
element.
If a non-interactive element is required thenonclick
should be accompanied by anonkeyup
oronkeydown
handler that enables the user to perform equivalent actions via the keyboard. In order for the user to be able to trigger a key press, the element will also need to be focusable by adding atabindex
. While anonkeypress
handler will also silence this warning, it should be noted that thekeypress
event is deprecated.
<!-- A11y: visible, non-interactive elements with an onclick event must be accompanied by a keyboard event handler. --><divonclick={()=>{}}></div>
Coding for the keyboard is important for users with physical disabilities who cannot use a mouse, AT compatibility, and screenreader users.
a11y_consider_explicit_label
Buttons and links should either contain text or have an `aria-label` or `aria-labelledby` attribute
a11y_distracting_elements
Avoid `<%name%>` elements
Enforces that no distracting elements are used. Elements that can be visually distracting can cause accessibility issues with visually impaired users. Such elements are most likely deprecated, and should be avoided.
The following elements are visually distracting:<marquee>
and<blink>
.
<!-- A11y: Avoid <marquee> elements --><marquee></marquee>
a11y_figcaption_index
`<figcaption>` must be first or last child of `<figure>`
a11y_figcaption_parent
`<figcaption>` must be an immediate child of `<figure>`
Enforce that certain DOM elements have the correct structure.
<!-- A11y: <figcaption> must be an immediate child of <figure> --><div><figcaption>Image caption</figcaption></div>
a11y_hidden
`<%name%>` element should not be hidden
Certain DOM elements are useful for screen reader navigation and should not be hidden.
<!-- A11y: <h2> element should not be hidden --><h2aria-hidden="true">invisible header</h2>
a11y_img_redundant_alt
Screenreaders already announce `<img>` elements as an image
Enforce img alt attribute does not contain the word image, picture, or photo. Screen readers already announceimg
elements as an image. There is no need to use words such asimage,photo, and/orpicture.
<imgsrc="foo"alt="Foo eating a sandwich."/><!-- aria-hidden, won't be announced by screen reader --><imgsrc="bar"aria-hidden="true"alt="Picture of me taking a photo of an image"/><!-- A11y: Screen readers already announce <img> elements as an image. --><imgsrc="foo"alt="Photo of foo being weird."/><!-- A11y: Screen readers already announce <img> elements as an image. --><imgsrc="bar"alt="Image of me at a bar!"/><!-- A11y: Screen readers already announce <img> elements as an image. --><imgsrc="foo"alt="Picture of baz fixing a bug."/>
a11y_incorrect_aria_attribute_type
The value of '%attribute%' must be a %type%
Enforce that only the correct type of value is used for aria attributes. For example,aria-hidden
should only receive a boolean.
<!-- A11y: The value of 'aria-hidden' must be exactly one of true or false --><divaria-hidden="yes"></div>
a11y_incorrect_aria_attribute_type_boolean
The value of '%attribute%' must be either 'true' or 'false'. It cannot be empty
a11y_incorrect_aria_attribute_type_id
The value of '%attribute%' must be a string that represents a DOM element ID
a11y_incorrect_aria_attribute_type_idlist
The value of '%attribute%' must be a space-separated list of strings that represent DOM element IDs
a11y_incorrect_aria_attribute_type_integer
The value of '%attribute%' must be an integer
a11y_incorrect_aria_attribute_type_token
The value of '%attribute%' must be exactly one of %values%
a11y_incorrect_aria_attribute_type_tokenlist
The value of '%attribute%' must be a space-separated list of one or more of %values%
a11y_incorrect_aria_attribute_type_tristate
The value of '%attribute%' must be exactly one of true, false, or mixed
a11y_interactive_supports_focus
Elements with the '%role%' interactive role must have a tabindex value
Enforce that elements with an interactive role and interactive handlers (mouse or key press) must be focusable or tabbable.
<!-- A11y: Elements with the 'button' interactive role must have a tabindex value. --><divrole="button"onkeypress={()=>{}} />
a11y_invalid_attribute
'%href_value%' is not a valid %href_attribute% attribute
Enforce that attributes important for accessibility have a valid value. For example,href
should not be empty,'#'
, or#"Copy to clipboard" aria-label="Copy to clipboard">
<!-- A11y: '' is not a valid href attribute --><ahref="">invalid</a>
a11y_label_has_associated_control
A form label must be associated with a control
Enforce that a label tag has a text label and an associated control.
There are two supported ways to associate a label with a control:
- Wrapping a control in a label tag.
- Adding
for
to a label and assigning it the ID of an input on the page.
<labelfor="id">B</label><label>C <inputtype="text"/></label><!-- A11y: A form label must be associated with a control. --><label>A</label>
a11y_media_has_caption
`<video>` elements must have a `<track kind="captions">`
Providing captions for media is essential for deaf users to follow along. Captions should be a transcription or translation of the dialogue, sound effects, relevant musical cues, and other relevant audio information. Not only is this important for accessibility, but can also be useful for all users in the case that the media is unavailable (similar toalt
text on an image when an image is unable to load).
The captions should contain all important and relevant information to understand the corresponding media. This may mean that the captions are not a 1:1 mapping of the dialogue in the media content. However, captions are not necessary for video components with themuted
attribute.
<video><trackkind="captions"/></video><audiomuted></audio><!-- A11y: Media elements must have a <track kind=\"captions\"> --><video></video><!-- A11y: Media elements must have a <track kind=\"captions\"> --><video><track/></video>
a11y_misplaced_role
`<%name%>` should not have role attribute
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for examplemeta
,html
,script
,style
. This rule enforces that these DOM elements do not contain therole
props.
<!-- A11y: <meta> should not have role attribute --><metarole="tooltip"/>
a11y_misplaced_scope
The scope attribute should only be used with `<th>` elements
The scope attribute should only be used on<th>
elements.
<!-- A11y: The scope attribute should only be used with <th> elements --><divscope="row"/>
a11y_missing_attribute
`<%name%>` element should have %article% %sequence% attribute
Enforce that attributes required for accessibility are present on an element. This includes the following checks:
<a>
should have an href (unless it’s afragment-defining tag)<area>
should have alt, aria-label, or aria-labelledby<html>
should have lang<iframe>
should have title<img>
should have alt<object>
should have title, aria-label, or aria-labelledby<input type="image">
should have alt, aria-label, or aria-labelledby
<!-- A11y: <input type=\"image\"> element should have an alt, aria-label or aria-labelledby attribute --><inputtype="image"/><!-- A11y: <html> element should have a lang attribute --><html></html><!-- A11y: <a> element should have an href attribute --><a>text</a>
a11y_missing_content
`<%name%>` element should contain text
Enforce that heading elements (h1
,h2
, etc.) and anchors have content and that the content is accessible to screen readers
<!-- A11y: <a> element should have child content --><ahref="/foo"></a><!-- A11y: <h1> element should have child content --><h1></h1>
a11y_mouse_events_have_key_events
'%event%' event must be accompanied by '%accompanied_by%' event
Enforce thatonmouseover
andonmouseout
are accompanied byonfocus
andonblur
, respectively. This helps to ensure that any functionality triggered by these mouse events is also accessible to keyboard users.
<!-- A11y: onmouseover must be accompanied by onfocus --><divonmouseover={handleMouseover} /><!-- A11y: onmouseout must be accompanied by onblur --><divonmouseout={handleMouseout} />
a11y_no_abstract_role
Abstract role '%role%' is forbidden
a11y_no_interactive_element_to_noninteractive_role
`<%element%>` cannot have role '%role%'
WAI-ARIA roles should not be used to convert an interactive element to a non-interactive element. Non-interactive ARIA roles includearticle
,banner
,complementary
,img
,listitem
,main
,region
andtooltip
.
<!-- A11y: <textarea> cannot have role 'listitem' --><textarearole="listitem"></textarea>
a11y_no_noninteractive_element_interactions
Non-interactive element `<%element%>` should not be assigned mouse or keyboard event listeners
A non-interactive element does not support event handlers (mouse and key handlers). Non-interactive elements include<main>
,<area>
,<h1>
(,<h2>
, etc),<p>
,<img>
,<li>
,<ul>
and<ol>
. Non-interactiveWAI-ARIA roles includearticle
,banner
,complementary
,img
,listitem
,main
,region
andtooltip
.
<!-- `A11y: Non-interactive element <li> should not be assigned mouse or keyboard event listeners.` --><lionclick={()=>{}}></li><!-- `A11y: Non-interactive element <div> should not be assigned mouse or keyboard event listeners.` --><divrole="listitem"onclick={()=>{}}></div>
a11y_no_noninteractive_element_to_interactive_role
Non-interactive element `<%element%>` cannot have interactive role '%role%'
WAI-ARIA roles should not be used to convert a non-interactive element to an interactive element. Interactive ARIA roles includebutton
,link
,checkbox
,menuitem
,menuitemcheckbox
,menuitemradio
,option
,radio
,searchbox
,switch
andtextbox
.
<!-- A11y: Non-interactive element <h3> cannot have interactive role 'searchbox' --><h3role="searchbox">Button</h3>
a11y_no_noninteractive_tabindex
noninteractive element cannot have nonnegative tabIndex value
Tab key navigation should be limited to elements on the page that can be interacted with.
<!-- A11y: noninteractive element cannot have nonnegative tabIndex value --><divtabindex="0"></div>
a11y_no_redundant_roles
Redundant role '%role%'
Some HTML elements have default ARIA roles. Giving these elements an ARIA role that is already set by the browserhas no effect and is redundant.
<!-- A11y: Redundant role 'button' --><buttonrole="button">...</button><!-- A11y: Redundant role 'img' --><imgrole="img"src="foo.jpg"/>
a11y_no_static_element_interactions
`<%element%>` with a %handler% handler must have an ARIA role
Elements like<div>
with interactive handlers likeclick
must have an ARIA role.
<!-- A11y: <div> with click handler must have an ARIA role --><divonclick={()=>''}></div>
a11y_positive_tabindex
Avoid tabindex values above zero
Avoid positivetabindex
property values. This will move elements out of the expected tab order, creating a confusing experience for keyboard users.
<!-- A11y: avoid tabindex values above zero --><divtabindex="1"></div>
a11y_role_has_required_aria_props
Elements with the ARIA role "%role%" must have the following attributes defined: %props%
Elements with ARIA roles must have all required attributes for that role.
<!-- A11y: A11y: Elements with the ARIA role "checkbox" must have the following attributes defined: "aria-checked" --><spanrole="checkbox"aria-labelledby="foo"tabindex="0"></span>
a11y_role_supports_aria_props
The attribute '%attribute%' is not supported by the role '%role%'
Elements with explicit or implicit roles defined contain onlyaria-*
properties supported by that role.
<!-- A11y: The attribute 'aria-multiline' is not supported by the role 'link'. --><divrole="link"aria-multiline></div><!-- A11y: The attribute 'aria-required' is not supported by the role 'listitem'. This role is implicit on the element <li>. --><liaria-required></li>
a11y_role_supports_aria_props_implicit
The attribute '%attribute%' is not supported by the role '%role%'. This role is implicit on the element `<%name%>`
Elements with explicit or implicit roles defined contain onlyaria-*
properties supported by that role.
<!-- A11y: The attribute 'aria-multiline' is not supported by the role 'link'. --><divrole="link"aria-multiline></div><!-- A11y: The attribute 'aria-required' is not supported by the role 'listitem'. This role is implicit on the element <li>. --><liaria-required></li>
a11y_unknown_aria_attribute
Unknown aria attribute 'aria-%attribute%'
Unknown aria attribute 'aria-%attribute%'. Did you mean '%suggestion%'?
Enforce that only known ARIA attributes are used. This is based on theWAI-ARIA States and Properties spec.
<!-- A11y: Unknown aria attribute 'aria-labeledby' (did you mean 'labelledby'?) --><inputtype="image"aria-labeledby="foo"/>
a11y_unknown_role
Unknown role '%role%'
Unknown role '%role%'. Did you mean '%suggestion%'?
Elements with ARIA roles must use a valid, non-abstract ARIA role. A reference to role definitions can be found atWAI-ARIA site.
<!-- A11y: Unknown role 'toooltip' (did you mean 'tooltip'?) --><divrole="toooltip"></div>
attribute_avoid_is
The "is" attribute is not supported cross-browser and should be avoided
attribute_global_event_reference
You are referencing `globalThis.%name%`. Did you forget to declare a variable with that name?
attribute_illegal_colon
Attributes should not contain ':' characters to prevent ambiguity with Svelte directives
attribute_invalid_property_name
'%wrong%' is not a valid HTML attribute. Did you mean '%right%'?
attribute_quoted
Quoted attributes on components and custom elements will be stringified in a future version of Svelte. If this isn't what you want, remove the quotes
bidirectional_control_characters
A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can makedefabc
look likeabcdef
. As a result, if you were to unknowingly copy and paste some code that has these control characters, they may alter the behavior of your code in ways you did not intend. Seetrojansource.codes for more information.
bind_invalid_each_rest
The rest operator (...) will create a new object and binding '%name%' with the original object will not work
block_empty
Empty block
component_name_lowercase
`<%name%>` will be treated as an HTML element unless it begins with a capital letter
css_unused_selector
Unused CSS selector "%name%"
Svelte traverses both the template and the<style>
tag to find out which of the CSS selectors are not used within the template, so it can remove them.
In some situations a selector may target an element that is not ‘visible’ to the compiler, for example because it is part of an{@html ...}
tag or you’re overriding styles in a child component. In these cases, use:global
to preserve the selector as-is:
<divclass="post">{@htmlcontent}</div><style>.post:global {p{...}}</style>
custom_element_props_identifier
Using a rest element or a non-destructured declaration with `$props()` means that Svelte can't infer what properties to expose when creating a custom element. Consider destructuring all the props or explicitly specifying the `customElement.props` option.
element_implicitly_closed
This element is implicitly closed by the following `%tag%`, which can cause an unexpected DOM structure. Add an explicit `%closing%` to avoid surprises.
In HTML, some elements are implicitly closed by another element. For example, you cannot nest a<p>
inside another<p>
:
<!-- this HTML... --><p><p>hello</p><!-- results in this DOM structure --><p></p><p>hello</p>
Similarly, a parent element’s closing tag will implicitly close all child elements, even if the</
was a typo and you meant to create anew element. To avoid ambiguity, it’s always a good idea to have an explicit closing tag.
element_invalid_self_closing_tag
Self-closing HTML tags for non-void elements are ambiguous — use `<%name% ...></%name%>` rather than `<%name% ... />`
In HTML, there’sno such thing as a self-closing tag. While thislooks like a self-contained element with some text next to it...
<div><spanclass="icon"/> some text!</div>
...a spec-compliant HTML parser (such as a browser) will in fact parse it like this, with the textinside the icon:
<div><spanclass="icon"> some text! </span></div>
Some templating languages (including Svelte) will ‘fix’ HTML by turning<span />
into<span></span>
. Others adhere to the spec. Both result in ambiguity and confusion when copy-pasting code between different contexts, and as such Svelte prompts you to resolve the ambiguity directly by having an explicit closing tag.
To automate this, run the dedicated migration:
npxsvmigrateself-closing-tags
In a future version of Svelte, self-closing tags may be upgraded from a warning to an error.
event_directive_deprecated
Using `on:%name%` to listen to the %name% event is deprecated. Use the event attribute `on%name%` instead
Seethe migration guide for more info.
export_let_unused
Component has unused export property '%name%'. If it is for external reference only, please consider using `export const %name%`
legacy_code
`%code%` is no longer valid — please use `%suggestion%` instead
legacy_component_creation
Svelte 5 components are no longer classes. Instantiate them using `mount` or `hydrate` (imported from 'svelte') instead.
See themigration guide for more info.
node_invalid_placement_ssr
%message%. When rendering this component on the server, the resulting HTML will be modified by the browser (by moving, removing, or inserting elements), likely resulting in a `hydration_mismatch` warning
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:
<p>hello <div>world</div></p>
will result in<p>hello </p><div>world</div><p></p>
(the<div>
autoclosed the<p>
because<p>
cannot contain block-level elements)<option><div>option a</div></option>
will result in<option>option a</option>
(the<div>
is removed)<table><tr><td>cell</td></tr></table>
will result in<table><tbody><tr><td>cell</td></tr></tbody></table>
(a<tbody>
is auto-inserted)
This code will work when the component is rendered on the client (which is why this is a warning rather than an error), but if you use server rendering it will cause hydration to fail.
non_reactive_update
`%name%` is updated, but is not declared with `$state(...)`. Changing its value will not correctly trigger updates
This warning is thrown when the compiler detects the following:
- a variable was declared without
$state
or$state.raw
- the variable is reassigned
- the variable is read in a reactive context
In this case, changing the value will not correctly trigger updates. Example:
<script>letreactive=$state('reactive');letstale='stale';</script><p>This value updates: {reactive}</p><p>This value does not update: {stale}</p><buttononclick={()=>{stale='updated';reactive='updated';}}>update</button>
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
<scriptcontext="module"module>letfoo='bar';</script>
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 `<slot>` to render parent content is deprecated. Use `{@render ...}` tags instead
Seethe migration guide 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:
<script>import{ setContext }from'svelte';letcount=$state(0);// warning: state_referenced_locallysetContext('count',count);</script><buttononclick={()=>count++}>increment</button>
<scriptlang="ts">import{ setContext }from'svelte';letcount=$state(0);// warning: state_referenced_locallysetContext('count',count);</script><buttononclick={()=>count++}>increment</button>
<script>import{ getContext }from'svelte';constcount=getContext('count');</script><!-- This will never update --><p>The count is {count}</p>
<scriptlang="ts">import{ getContext }from'svelte';constcount=getContext('count');</script><!-- This will never update --><p>The count is {count}</p>
To fix this, reference the variable such that it is lazily evaluated. For the above example, this can be achieved by wrappingcount
in a function:
<script>import{ setContext }from'svelte';letcount=$state(0);setContext('count',()=>count);</script><buttononclick={()=>count++}>increment</button>
<scriptlang="ts">import{ setContext }from'svelte';letcount=$state(0);setContext('count',()=>count);</script><buttononclick={()=>count++}>increment</button>
<script>import{ getContext }from'svelte';constcount=getContext('count');</script><!-- This will update --><p>The count is {count()}</p>
<scriptlang="ts">import{ getContext }from'svelte';constcount=getContext('count');</script><!-- This will update --><p>The count is {count()}</p>
For more info, seePassing 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
`<svelte:component>` 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<X>
to re-render whenX
changed, you would either have to use<svelte:component this={X}>
or put the component inside a{#key X}...{/key}
block.
In Svelte 5 this is no longer true — ifX
changes,<X>
re-renders.
In some cases<object.property>
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:
{#eachitemsasitem}<svelte:componentthis={item.condition?Y:Z} />{@constComponent=item.condition?Y:Z}<Component/>{/each}
A derived value may be used in other contexts:
<script>// ...letcondition=$state(false);constComponent=$derived(condition?Y:Z);</script><svelte:componentthis={condition?Y:Z} /><Component/>
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
`<svelte:self>` is deprecated — use self-imports (e.g. `import %name% from './%basename%'`) instead
Seethe note in the docs for more info.
unknown_code
`%code%` is not a recognised code
`%code%` is not a recognised code (did you mean `%suggestion%`?)
Edit this page on GitHub llms.txt