Svelte and SvelteKit course Β· Module 2: Components

Special Svelte Elements

3 min read Β·
In this lesson6

Svelte offers special elements for handling advanced use cases. Before you meet them - two tricks that needed special elements in Svelte 4, while in Svelte 5 ordinary components do the job.

Recursion - a Component Imports Itself

A component can render itself. In Svelte 5 it simply imports its own file:

<!-- TreeNode.svelte - Branches of Yggdrasil -->
<script>
  import TreeNode from './TreeNode.svelte';

  let { node, depth = 0 } = $props();
</script>

<div class="node" style="margin-left: {depth * 20}px">
  <span>{node.name}</span>

  {#if node.children}
    {#each node.children as child}
      <TreeNode node={child} depth={depth + 1} />
    {/each}
  {/if}
</div>

<style>
  .node {
    padding: 0.5rem;
    border-left: 2px solid #4a7c23;
  }
</style>

Usage:

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

  const yggdrasil = {
    name: 'Yggdrasil',
    children: [
      { name: 'Asgard', children: [{ name: 'Valhalla' }] },
      { name: 'Midgard', children: [{ name: 'Svenheim' }] },
      { name: 'Niflheim' }
    ]
  };
</script>

<TreeNode node={yggdrasil} />

In Svelte 4 the <svelte:self> element was used for this. In Svelte 5 it is deprecated - the component imports itself.

Dynamic Component

In Svelte 5 components are dynamic on their own: if the variable holding a component changes, Svelte renders the new one. Just store the component in a variable whose name starts with a capital letter and use it like a tag:

<script>
  import Warrior from './Warrior.svelte';
  import Ship from './Ship.svelte';
  import Treasure from './Treasure.svelte';

  const components = {
    warrior: Warrior,
    ship: Ship,
    treasure: Treasure
  };

  let selected = $state('warrior');
  let Selected = $derived(components[selected]);
</script>

<select bind:value={selected}>
  <option value="warrior">Warrior</option>
  <option value="ship">Ship</option>
  <option value="treasure">Treasure</option>
</select>

<Selected />

In Svelte 4 you had to write <svelte:component this={...} />. In Svelte 5 that element is deprecated.

svelte:element - Dynamic HTML Element

<script>
  let { level = 1, text } = $props();

  // h1, h2, h3... dynamically
  let tag = $derived(`h${Math.min(level, 6)}`);
</script>

<svelte:element this={tag}>
  {text}
</svelte:element>

svelte:window - Window Events

You attach events to the browser window the same way as to ordinary elements - with attributes such as onkeydown. bind: bindings need variables created with $state:

<script>
  let innerWidth = $state(0);
  let innerHeight = $state(0);
  let scrollY = $state(0);

  function handleKeydown(event) {
    if (event.key === 'Escape') {
      console.log('Escape pressed!');
    }
  }
</script>

<svelte:window
  bind:innerWidth
  bind:innerHeight
  bind:scrollY
  onkeydown={handleKeydown}
/>

<p>Window size: {innerWidth} x {innerHeight}</p>
<p>Scroll: {scrollY}px</p>

svelte:document and svelte:body

<script>
  function handleVisibility() {
    console.log('Tab visibility:', document.visibilityState);
  }

  function handleMouseEnter() {
    console.log('The cursor is back on the page');
  }
</script>

<svelte:document onvisibilitychange={handleVisibility} />

<svelte:body onmouseenter={handleMouseEnter} />

svelte:head - Meta in head

<script>
  let { title = 'Land of the Vikings' } = $props();
</script>

<svelte:head>
  <title>{title}</title>
  <meta name="description" content="Learning Svelte in the land of the Vikings" />
</svelte:head>

Special elements are runes of power for special occasions - reach for them when plain HTML is not enough.

Docs entries used in this lesson

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. How can a component render itself (recursion) in Svelte 5?

  2. 2. How do you render a component stored in a variable in Svelte 5?

  3. 3. Which special element do we use to modify the page's <head> section?

Hands-on tasks in the game

  • Code editor

    Complete the code to listen for the keydown event

Useful articles