Svelte is a web framework for writing rich user interfaces. Here’s a quick guide on Svelte 3.0.
The easiest way to learn Svelte (in my opinion) is the examples documentation. It’s comprehensive and straight-to-the-point.
Svelte components store the markup, script and CSS styles in one .svelte file.
<script> let name = "Rico";</script><div> hello {name}!</div><style> div { color: dodgerblue; }</style>Using export let will define a component property.
<script> import Nested from './Nested.svelte';</script><div> My message is: <Nested message="Hello there" /></div><script> export let message;</script><div> {message}</div><style> div { color: purple; }</style>Styles are scoped per component, but :global(…) will allow styling elements outside the component.
<p> Only this will be red.</p><style> p { color: red; } p :global(a) { color: blue; }</style>Attributes are in HTML syntax, and can contain JavaScript expressions inside {…} brackets.
<img src={src}><img src="{src}"><img src="https://{src}"><img {src}> <!-- shorthand --><img {...props}> <!-- spread -->Updating variables declared with let will trigger DOM updates.
<script> let count = 0; // state</script>
<button on:click={() => { count++ }}> I was clicked {count} times</button>Prefixing statements with $: will make it run with changes to the states it depends on.
<script> let count;
// reactive state derived from `count` $: doubled = count * 2;</script>6 collapsed lines
<button on:click={() => { count++ }}> Count: {count}</button>
<p>{count} * 2 = {doubled}</p>$: works with blocks too. Only values which directly appear within the $: block will become dependencies of the reactive statement.
<script> // runs when the `title` prop changes $: document.title = title;
// reactive block $: { console.log('title is', title); }</script>#if) {#if answer === 42} Yes{/if}:else) {#if answer === 42 && a !== b} Yes{:else if answer === 74 || b > c} Maybe{:else} No{/if}#each) {#each items as item} <li>{item.name} x {item.qty}</li>{/each}<!-- With index: -->{#each items as item, index} <li>{i + 1}: {item.name} x {item.qty}</li>{/each}The key expression allows for efficient adding and removing of items.
{#each users as user (user.id)} <UserCard {user} />{/each}Text expressions are automatically escaped unless @html is used.
<p>{string}</p><p>{@html string}</p>bind:value forms a two-way binding to a state variable.
<script> let name = '';</script><label> Name: <input bind:value={name} /></label><p>Hello {name || 'stranger'}!</p>bind:checked binds the checked state of a checkbox to a state variable.
<script> let subscribed = false;</script><label> <input bind:checked={subscribed} /> Subscribe to the newsletter</label>{#if subscribed} <p>Thank you for subscribing!</p>{/if}bind:group binds a variable to a group of elements, such as a radio button group.
<script> let flavor;</script><fieldset> Flavor: <input type='radio' bind:group={flavor} value='vanilla'> <input type='radio' bind:group={flavor} value='mint'></fieldset><svelte:head> allows inserting elements into the document head.
<svelte:head> <meta name="robots" content="noindex"></svelte:head><svelte:body> allows binding DOM events to the body element.
<svelte:body on:mouseenter={handleMouseenter} on:mouseleave={handleMouseleave} use:someAction/>svelte:window allows manipulating window properties.
<svelte:window bind:innerWidth={width}/>innerWidthinnerHeightouterWidthouterHeightscrollX (rw)scrollY (rw)online<svelte:window> also allows binding DOM events to the window object.
<svelte:window on:keydown={handleKeydown}/>Slots allow passing content to a component (“children”).
<script> import Notice from './Notice.svelte'</script><Notice> There will be rain today.</Notice><div class='notice'> <strong>Notice:</strong> <slot></slot></div>Use named slots to pass more than 1 group of children elements.
<MyDialog> <h1 slot='header'>Forecast:</h1> There will be rain today. <div slot='footer'>23°C, Rain</div></MyDialog><dialog class='my-dialog'> <header> <slot name='header'></slot> </header>
<slot></slot>
<footer> <slot name='footer'></slot> </footer></dialog><svelte:fragment slot="items"> <li>Apple</li> <li>Banana</li> <li>Cherry</li></svelte:fragment><slot name="items"></slot><slot prop={value}></slot><slot prop={value}> This is fallback content</slot><script> import { onMount } from 'svelte'; let canvasEl; onMount(() => { drawOn(canvasEl.getContext('2d')); });</script>
<canvas bind:this={canvasEl}></canvas>Docs: bind:this
I am a web developer helping make the world a better place through JavaScript, Ruby, and UI design. I write articles like these often. If you'd like to stay in touch, subscribe to my list.