You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/documentation/docs/02-template-syntax/02-basic-markup.md

7.5 KiB

title
Basic markup

Tags

A lowercase tag, like <div>, denotes a regular HTML element. A capitalised tag, such as <Widget> or <Namespace.Widget>, indicates a component.

<script>
	import Widget from './Widget.svelte';
</script>

<div>
	<Widget />
</div>

Attributes and props

By default, attributes work exactly like their HTML counterparts.

<div class="foo">
	<button disabled>can't touch this</button>
</div>

As in HTML, values may be unquoted.

<input type=checkbox />

Attribute values can contain JavaScript expressions.

<a href="page/{p}">page {p}</a>

Or they can be JavaScript expressions.

<button disabled={!clickable}>...</button>

Boolean attributes are included on the element if their value is truthy and excluded if it's falsy.

All other attributes are included unless their value is nullish (null or undefined).

<input required={false} placeholder="This input field is not required" />
<div title={null}>This div has no title attribute</div>

Quoting a singular expression does not affect how the value is parsed yet, but in Svelte 6 it will:

<button disabled="{number !== 42}">...</button>

When the attribute name and value match (name={name}), they can be replaced with {name}.

<button {disabled}>...</button>
<!-- equivalent to
<button disabled={disabled}>...</button>
-->

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.

<Widget foo={bar} answer={42} text="hello" />

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.

<Widget {...things} />

The value attribute of an input element or its children option elements must not be set with spread attributes when using bind:group or bind:checked. Svelte needs to be able to see the element's value directly in the markup in these cases so that it can link it to the bound variable.

Sometimes, the attribute order matters as Svelte sets attributes sequentially in JavaScript. For example, <input type="range" min="0" max="1" value={0.5} step="0.1"/>, Svelte will attempt to set the value to 1 (rounding up from 0.5 as the step by default is 1), and then set the step to 0.1. To fix this, change it to <input type="range" min="0" max="1" step="0.1" value={0.5}/>.

Another example is <img src="..." loading="lazy" />. Svelte will set the img src before making the img element loading="lazy", which is probably too late. Change this to <img loading="lazy" src="..."> to make the image lazily loaded.

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:

<button onclick={() => console.log('clicked')}>click me</button>

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: <button {onclick}>click me</button>
  • you can spread them: <button {...thisSpreadContainsEventAttributes}>click me</button>
  • component events are just (callback) properties and don't need a separate concept

Timing-wise, event attributes always fire after events from bindings (e.g. oninput always fires after an update to bind:value). Under the hood, events are either listened to directly through addEventListener, or the event is delegated.

Event delegation

To reduce the memory footprint and increase performance, Svelte uses a technique called event delegation. This means that certain events are only listened to once at the application root, invoking a handler that then traverses the event call path and invokes listeners along the way.

There are a few gotchas you need to be aware of when it comes to event delegation:

  • when you manually dispatch an event with the same name as one of the delegated ones, make sure to set the { bubbles: true } option
  • when listening to events programmatically (i.e. not through <button onclick={...}> but through node.addEventListener), be careful to not call stopPropagation or else the delegated event handler won't be reached and handlers won't be invoked. Similarly, event listeners added manually and higher up the DOM tree will be invoked before events that are delegated and deeper down the DOM tree (because the actual event reaction happens in the delegated handler at the root). For these reasons it's best to use on (which properly handles stopPropagation) from svelte/events instead of addEventListener to make sure the chain of events is preserved

The following events 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}

Curly braces can be included in a Svelte template by using their HTML entity strings: &lbrace;, &lcub;, or &#123; for { and &rbrace;, &rcub;, or &#125; for }.

If you're using a regular expression (RegExp) literal notation, you'll need to wrap it in parentheses.

<h1>Hello {name}!</h1>
<p>{a} + {b} = {a + b}.</p>

<div>{(/^[A-Za-z ]+$/).test(value) ? x : y}</div>

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

Comments

You can use HTML comments inside components.

<!-- this is a comment! --><h1>Hello world</h1>

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.

<!-- svelte-ignore a11y-autofocus -->
<input bind:value={name} autofocus />

You can add a special comment starting with @component that will show up when hovering over the component name in other files.

<!--
@component
- You can use markdown here.
- You can also use code blocks here.
- Usage:
  ```html
  <Main name="Arethra">
  ```
-->
<script>
	let { name } = $props();
</script>

<main>
	<h1>
		Hello, {name}
	</h1>
</main>