Svelte logo

Svelte by Example: Special Elements

Svelte supports a set of special elements to work with the page around a component.

In this example, we'll briefly review Svelte's special elements.

Use svelte:element to dynamically render an HTML element.

Heading.svelte
<script>
  let { level = 1, title = 'Todo List' } = $props();
</script>


<svelte:element this={level === 1 ? 'h1' : 'h2'}>
  {title}
</svelte:element>

Use svelte:window to listen for window events or bind to a window property. Svelte takes care of removing listeners, and won't access window on the server.

TodoList.svelte
<script>
  let scrollY = $state(0);
</script>


<svelte:window bind:scrollY />
<p>You've scrolled {scrollY} pixels through your todos.</p>

Use svelte:body and svelte:document to listen for events on the body or document.

TodoList.svelte
<script>
  let lastKey = $state('');
  function handleKeydown(event) {
    lastKey = event.key;
  }
</script>

<svelte:document onkeydown={handleKeydown} />
<svelte:body onclick={() => lastKey = ''} />
<p>Last key: {lastKey}</p>

Use svelte:head to add contents to the document's <head>.

<svelte:head>
  <title>Todo List</title>
</svelte:head>

Use svelte:options to specify compiler options for a component. runes explicitly enables runes mode.

<svelte:options runes={true} />

<h1>Todo List</h1>

Dynamic Components

In runes mode, component references are reactive. Render a variable directly instead of using svelte:component.

TodoList.svelte
<script>
  import Todo from './Todo.svelte';
  import CompletedTodo from './CompletedTodo.svelte';
  let { todo } = $props();

  let Component = $derived(
    todo.completed ? CompletedTodo : Todo,
  );
</script>

<Component {...todo} />

For recursive components, import the component into itself and render it by name instead of using svelte:self. Snippets replace named slots and svelte:fragment.