Menu

Introduction

What is Svelte?

If you've ever built a JavaScript application, the chances are you've encountered – or at least heard of – frameworks like React, Angular, Vue and Ractive. Like Svelte, these tools all share a goal of making it easy to build slick interactive user interfaces.

But Svelte has a crucial difference: rather than interpreting your application code at run time, your app is converted into ideal JavaScript at build time. That means you don't pay the performance cost of the framework's abstractions, or incur a penalty when your app first loads.

And because there's no overhead, you can easily adopt Svelte in an existing app incrementally, or ship widgets as standalone packages that work anywhere.

Read the introductory blog post to learn more about Svelte's goals and philosophy.

Understanding Svelte components

In Svelte, an application is composed from one or more components. A component is a reusable self-contained block of code that encapsulates markup, styles and behaviours that belong together.

Like Ractive and Vue, Svelte promotes the concept of single-file components: a component is just an .html file. Here's a simple example:

<!-- App.html -->
<h1>Hello {{name}}!</h1>

Svelte turns this into a JavaScript module that you can import into your app:

// main.js
import App from './App.html';

const app = new App({
  target: document.querySelector( 'main' ),
  data: { name: 'world' }
});

// change the data associated with the template
app.set({ name: 'everybody' });

// detach the component and clean everything up
app.destroy();

Congratulations, you've just learned about half of Svelte's API!

Getting started

Normally, this is the part where the instructions might tell you to add the framework to your page as a <script> tag. But because Svelte runs at build time, it works a little bit differently.

The best way to use Svelte is to integrate it into your build system – there are plugins for Rollup, Browserify, Gulp and others, with more on the way. See here for an up-to-date list.

Right now, for the purposes of demonstration, we'll use svelte-cli, the command line interface.

You will need to have Node.js installed, and have some familiarity with the command line

First, install the CLI:

npm install -g svelte-cli

Then, create a directory for the project:

mkdir my-svelte-project
cd my-svelte-project

Inside my-svelte-project, create a HelloWorld.html file with the following contents:

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

Compile it:

svelte compile --format iife HelloWorld.html > HelloWorld.js

The --format iife bit means 'generate an immediately-invoked function expression' – this allows us to use the component as a simple <script> tag. (By default, Svelte will create a JavaScript module instead, which is recommended for more serious applications but requires additional steps.)

Create an index.html page and include the script we just generated:

<!doctype html>
<html>
<head>
  <title>My first Svelte app</title>
</head>
<body>
  <main></main>
  <script src='HelloWorld.js'></script>
  <script>
    var app = new HelloWorld({
      target: document.querySelector( 'main' ),
      data: {
        name: 'world'
      }
    });
  </script>
</body>
</html>

Finally, open the page in your browser – open index.html – and interact with app via the console using the API.

Component API

As we saw above, you create a component instance with the new keyword:

import MyComponent from './MyComponent.html';

const component = new MyComponent({
  // `target` is the only required option – the element
  // to render the component to
  target: document.querySelector( 'main' ),

  // `data` is optional. A component can also have
  // default data – we'll learn about that later.
  data: {
    questions: [
      'life',
      'the universe',
      'everything'
    ],
    answer: 42
  }
});

Every Svelte component instance has a small number of methods you can use to control it, in addition to any custom methods you add.

component.set(data)

This updates the component's state with the new values provided and causes the DOM to update. data must be a plain old JavaScript object (POJO). Any properties not included in data will remain as they were.

component.set({
  questions: [
    'why is the sky blue?',
    'how do planes fly?',
    'where do babies come from?'
  ],
  answer: 'ask your mother'
});

If you've used Ractive in the past, this is very similar to ractive.set(...), except that instead of doing ractive.set('foo', 'bar') you must always do ractive.set({foo: 'bar'}), and you cannot set nested keypaths directly. It's also very similar to React's setState, except that it causes synchronous updates, meaning the DOM is always in a predictable state.

component.get(key)

Returns the current value of key:

console.log( component.get( 'answer' ) ); // 'ask your mother'

This will also retrieve the value of computed properties.

component.observe(key, callback[, options])

This method allows you to respond to changes in state, which is particularly useful when combined with lifecycle hooks and two-way bindings.

const observer = component.observe( 'answer', answer => {
  console.log( `the answer is ${answer}` );
});
// fires immediately with current answer:
// -> 'the answer is ask your mother'

component.set({ answer: 'google it' });
// -> 'the answer is google it'

observer.cancel(); // further changes will be ignored

The callback takes two arguments – the current value and the previous value. (The first time it is called, the second argument will be undefined):

thermometer.observe( 'temperature', ( newValue, oldValue ) => {
  if ( oldValue === undefined ) return;
  console.log( `it's getting ${newValue > oldValue ? 'warmer' : 'colder'}` );
});

If you don't want the callback to fire when you first attach the observer, use init: false:

thermometer.observe( 'temperature', ( newValue, oldValue ) => {
  console.log( `it's getting ${newValue > oldValue ? 'warmer' : 'colder'}` );
}, { init: false });

For primitive values like strings and numbers, observer callbacks are only called when the value changes. But because it's possible to mutate an object or array while preserving referential equality, Svelte will err on the side of caution. In other words, if you do component.set({foo: component.get('foo')}), and foo is an object or array, any foo observers will be triggered.

By default, observers are called before the DOM updates, giving you a chance to perform any additional updates without touching the DOM more than is necessary. In some cases – for example, if you need to measure an element after the DOM has been updated – use defer: true:

function redraw () {
  canvas.width = drawingApp.get( 'width' );
  canvas.height = drawingApp.get( 'height' );
  updateCanvas();
}

drawingApp.observe( 'width', redraw, { defer: true });
drawingApp.observe( 'height', redraw, { defer: true });

To observe on a nested component, use refs:

<Widget ref:widget/>
<script>
  export default {
    oncreate () {
      this.refs.widget.observe( 'xxx', () => {...});
    }
  };
</script>

component.on(eventName, callback)

Allows you to respond to events:

const listener = component.on( 'thingHappened', event => {
  console.log( `A thing happened: ${event.thing}` );
});

// some time later...
listener.cancel();

component.fire(eventName, event)

The companion to component.on(...):

component.fire( 'thingHappened', {
  thing: 'this event was fired'
});

At first glance component.on(...) and component.fire(...) aren't particularly useful, but it'll become more so when we learn about nested components.

component.on(...) and component.observe(...) look quite similar, but they have different purposes. Observers are useful for reacting to data flowing through your application and changing continuously over time, whereas events are good for modeling discrete moments such as 'the user made a selection, and this is what it is'.

component.destroy()

Removes the component from the DOM and removes any observers and event listeners that were created. This will also fire a destroy event:

component.on( 'destroy', () => {
  alert( 'goodbye!' ); // please don't do this
});

component.destroy();

Template syntax

Rather than reinventing the wheel, Svelte templates are built on foundations that have stood the test of time: HTML, CSS and JavaScript. There's very little extra stuff to learn.

Tags

Tags allow you to bind data to your template. Whenever your data changes (for example after component.set(...)), the DOM updates automatically. You can use any JavaScript expression in templates, and it will also automatically update:

<p>{{a}} + {{b}} = {{a + b}}</p>

You can also use tags in attributes:

<h1 style='color: {{color}};'>{{color}}</h1>
<p hidden='{{hideParagraph}}'>You can hide this paragraph.</p>

Boolean attributes like hidden will be omitted if the tag expression evaluates to false.

While tags are delimited using {{ and }}, Svelte does not use Mustache syntax. Tags are just JavaScript expressions.

Triples

Ordinary tags render expressions as plain text. If you need your expression interpreted as HTML, wrap it in triple braces, {{{ and }}}.

<p>This HTML: {{html}}</p>
<p>Renders as: {{{html}}}</p>

As with tags, you can use any JavaScript expression in triples, and it will automatically update the document when your data changes.

Triples will not sanitize the HTML before rendering it! If you are displaying user input, you are responsible for first sanitizing it. Not doing so opens you up to all sorts of different attacks.

If blocks

Control whether or not part of your template is rendered by wrapping it in an if block.

{{#if user.loggedIn}}
  <a href='/logout'>log out</a>
{{/if}}

{{#if !user.loggedIn}}
  <a href='/login'>log in</a>
{{/if}}

You can combine the two blocks above with {{else}}:

{{#if user.loggedIn}}
  <a href='/logout'>log out</a>
{{else}}
  <a href='/login'>log in</a>
{{/if}}

You can also use {{elseif ...}}:

{{#if x > 10}}
  <p>{{x}} is greater than 10</p>
{{elseif 5 > x}}
  <p>{{x}} is less than 5</p>
{{else}}
  <p>{{x}} is between 5 and 10</p>
{{/if}}

Each blocks

Iterate over lists of data:

<h1>Cats of YouTube</h1>

<ul>
  {{#each cats as cat}}
    <li><a target='_blank' href='{{cat.video}}'>{{cat.name}}</a></li>
  {{/each}}
</ul>

You can access the index of the current element with expression as name, index:

<div class='grid'>
  {{#each rows as row, y}}
    <div class='row'>
      {{#each columns as column, x}}
        <code class='cell'>
          {{x + 1}},{{y + 1}}:
          <strong>{{row[column]}}</strong>
        </code>
      {{/each}}
    </div>
  {{/each}}
</div>

By default, if the list a, b, c becomes a, c, Svelte will remove the third block and change the second from b to c, rather than removing b. If that's not what you want, use a keyed each block.

Directives

The last place where Svelte template syntax differs from regular HTML: directives allow you to add special instructions for adding event handlers, two-way bindings, refs and so on. We'll cover each of those in later stages of this guide – for now, all you need to know is that directives can be identified by the : character:

<p>Count: {{count}}</p>
<button on:click='set({ count: count + 1 })'>+1</button>

Technically, the : character is used to denote namespaced attributes in HTML. These will not be treated as directives, if encountered.

Scoped styles

One of Svelte's key tenets is that components should be self-contained and reusable in different contexts. Because of that, it has a mechanism for scoping your CSS, so that you don't accidentally clobber other selectors on the page.

Adding styles

Your component template can have a <style> tag, like so:

<div class='foo'>
  Big red Comic Sans
</div>

<style>
  .foo {
    color: red;
    font-size: 2em;
    font-family: 'Comic Sans MS';
  }
</style>

How it works

Open the example above in the REPL and inspect the element to see what has happened – Svelte has added a svelte-[uniqueid] attribute to the element, and transformed the CSS selector accordingly. Since no other element on the page can share that selector, anything else on the page with class="foo" will be unaffected by our styles.

This is vastly simpler than achieving the same effect via Shadow DOM and works everywhere without polyfills.

Svelte will add a <style> tag to the page containing your scoped styles. Dynamically adding styles may be impossible if your site has a Content Security Policy. If that's the case, you can use scoped styles by server-rendering your CSS and using the css: false compiler option (or --no-css with the CLI).

Cascading rules

The usual cascading mechanism still applies – any global .foo styles would still be applied, and if our template had nested components with class="foo" elements, they would inherit our styles.

Scoped styles are not dynamic – they are shared between all instances of a component. In other words you can't use {{tags}} inside your CSS.

Behaviours

As well as scoped styles and a template, components can encapsulate behaviours. For that, we add a <script> element and export an object:

<div>
  <!-- template goes here -->
</div>

<script>
  export default {
    // behaviours go here
  };
</script>

Default data

Often, it makes sense for a component to have default data. This should be expressed as a function that returns a POJO:

<p>Count: {{count}}</p>
<button on:click='set({ count: count + 1 })'>+1</button>

<script>
  export default {
    data () {
      return {
        count: 0
      };
    }
  };
</script>

Data supplied at instantiation (i.e. new Component(...)) takes priority over defaults.

The example above, like many of the examples below, uses ES2015 syntax – i.e. data () {...} rather than data: function {...}. While Svelte will generate ES5 code that runs everywhere, it won't convert your ES2015 code into ES5 – so if you use ES2015 and need to support older browsers, you will need an additional transpilation step in your build process, added after the svelte() step, using Babel or Bublé.

Computed properties

Often, your program will use values that depend on other values – for example, you might have a filtered list, which depends on both the list and the filter. Normally in JavaScript you'd have to add logic to update the dependent property when any of the dependencies change. This is a frequent source of bugs, and it gets worse as your application grows.

Svelte allows you to express these dependencies in computed properties, which are recalculated whenever those dependencies change:

<p>
  The time is
  <strong>{{hours}}:{{minutes}}:{{seconds}}</strong>
</p>

<script>
  export default {
    data () {
      return {
        time: new Date()
      };
    },

    computed: {
      hours: time => time.getHours(),
      minutes: time => time.getMinutes(),
      seconds: time => time.getSeconds()
    }
  };
</script>

Notice that all we need to do to tell Svelte that hours, minutes and seconds depend on time is include it as a parameter to the function. There's no costly dependency tracking involved – the dependency graph is resolved at compile time.

computed must be an object literal, and the properties must be function expressions or arrow function expressions.

Lifecycle hooks

There are two 'hooks' provided by Svelte for adding control logic – oncreate and ondestroy:

<p>
  The time is
  <strong>{{hours}}:{{minutes}}:{{seconds}}</strong>
</p>

<script>
  export default {
    oncreate () {
      this.interval = setInterval( () => {
        this.set({ time: new Date() });
      }, 1000 );
    },

    ondestroy () {
      clearInterval( this.interval );
    },

    data () {
      return {
        time: new Date()
      };
    },

    computed: {
      hours: time => time.getHours(),
      minutes: time => time.getMinutes(),
      seconds: time => time.getSeconds()
    }
  };
</script>

Helpers

Helpers are simple functions that are used in your template. In the example above, we want to ensure that minutes and seconds are preceded with a 0 if they only have one digit, so we add a leftPad helper:

<p>
  The time is
  <strong>{{hours}}:{{leftPad(minutes, 2, '0')}}:{{leftPad(seconds, 2, '0')}}</strong>
</p>

<script>
  import leftPad from 'left-pad';

  export default {
    helpers: {
      leftPad
    },

    oncreate () {
      this.interval = setInterval( () => {
        this.set({ time: new Date() });
      }, 1000 );
    },

    ondestroy () {
      clearInterval( this.interval );
    },

    data () {
      return {
        time: new Date()
      };
    },

    computed: {
      hours: time => time.getHours(),
      minutes: time => time.getMinutes(),
      seconds: time => time.getSeconds()
    }
  };
</script>

Of course, you could use leftPad inside the computed properties instead of in the template. There's no hard and fast rule about when you should use expressions with helpers versus when you should use computed properties – do whatever makes your component easier for the next developer to understand.

Helper functions should be pure – in other words, they should not have side-effects, and their returned value should only depend on their arguments.

Custom methods

In addition to the built-in methods, you can add methods of your own:

<script>
  export default {
    methods: {
      say: function ( message ) {
        alert( message ); // again, please don't do this
      }
    }
  };
</script>

These become part of the component's API:

import MyComponent from './MyComponent.html';

var component = new MyComponent({
  target: document.querySelector( 'main' )
});

component.say( '👋' );

Methods (whether built-in or custom) can also be called inside event handlers:

<button on:click='say("hello")'>say hello!</button>

Custom event handlers

Soon, we'll learn about event handlers – if you want, skip ahead to that section first then come back here!

Most of the time you can make do with the standard DOM events (the sort you'd add via element.addEventListener, such as click) but sometimes you might need custom events to handle gestures, for example.

Custom events are just functions that take a node and a callback as their argument, and return an object with a teardown method that gets called when the element is removed from the page:

<button on:longpress='set({ done: true })'>click and hold</button>

{{#if done}}
  <p>clicked and held</p>
{{/if}}

<script>
  export default {
    events: {
      longpress ( node, callback ) {
        function onmousedown ( event ) {
          const timeout = setTimeout( () => callback( event ), 1000 );

          function cancel () {
            clearTimeout( timeout );
            node.removeEventListener( 'mouseup', cancel, false );
          }

          node.addEventListener( 'mouseup', cancel, false );
        }

        node.addEventListener( 'mousedown', onmousedown, false );

        return {
          teardown () {
            node.removeEventListener( 'mousedown', onmousedown, false );
          }
        };
      }
    }
  };
</script>

Namespaces

Components are assumed to be in the HTML namespace. If your component is designed to be used inside an <svg> element, you need to specify the namespace:

App.html

<svg viewBox='0 0 1000 1000' style='width: 100%; height: 100%;'> <SmileyFace x='70' y='280' size='100' fill='#f4d9c7'/> <SmileyFace x='800' y='250' size='150' fill='#40250f'/> <SmileyFace x='150' y='700' size='110' fill='#d2aa7a'/> <SmileyFace x='875' y='730' size='130' fill='#824e2e'/> <SmileyFace x='450' y='500' size='240' fill='#d2b198'/> </svg> <script> import SmileyFace from './SmileyFace.html'; export default { components: { SmileyFace } }; </script>

SmileyFace.html

<!-- CC-BY-SA — https://commons.wikimedia.org/wiki/File:718smiley.svg --> <g transform='translate({{x}},{{y}}) scale({{size / 366.5}})'> <circle r="366.5"/> <circle r="336.5" fill="{{fill}}"/> <path d="m-41.5 298.5c-121-21-194-115-212-233v-8l-25-1-1-18h481c6 13 10 27 13 41 13 94-38 146-114 193-45 23-93 29-142 26z"/> <path d="m5.5 280.5c52-6 98-28 138-62 28-25 46-56 51-87 4-20 1-57-5-70l-423-1c-2 56 39 118 74 157 31 34 72 54 116 63 11 2 38 2 49 0z" fill="#871945"/> <path d="m-290.5 -24.5c-13-26-13-57-9-85 6-27 18-52 35-68 21-20 50-23 77-18 15 4 28 12 39 23 18 17 30 40 36 67 4 20 4 41 0 60l-6 21z"/> <path d="m-132.5 -43.5c5-6 6-40 2-58-3-16-4-16-10-10-14 14-38 14-52 0-15-18-12-41 6-55 3-3 5-5 5-6-1-4-22-8-34-7-42 4-57.6 40-66.2 77-3 17-1 53 4 59h145.2z" fill="#fff"/> <path d="m11.5 -23.5c-2-3-6-20-7-29-5-28-1-57 11-83 15-30 41-52 72-60 29-7 57 0 82 15 26 17 45 49 50 82 2 12 2 33 0 45-1 10-5 26-8 30z"/> <path d="m198.5 -42.5c4-5 5-34 4-50-2-14-6-24-8-24-1 0-3 2-6 5-17 17-47 13-58-9-7-16-4-31 8-43 4-4 7-8 7-9 0 0-4-2-8-3-51-17-105 20-115 80-3 15 0 43 3 53z" fill="#fff"/> <path d="m137.5 223.5s-46 40-105 53c-66 15-114-7-114-7s14-76 93-95c76-18 126 49 126 49z" fill="#f9bedd"/> </g> <script> export default { // you can either use the shorthand 'svg', or the full // namespace: 'http://www.w3.org/2000/svg'. (I know // which one I prefer.) namespace: 'svg', data () { return { x: 100, y: 100, size: 100 }; } }; </script>

Nested components

As well as containing elements (and if blocks and each blocks), Svelte components can contain other Svelte components.

<div class='widget-container'>
  <Widget foo bar='static' baz='{{dynamic}}'/>
</div>

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

  export default {
    data () {
      return {
        dynamic: 'this can change'
      }
    },

    components: {
      Widget
    }
  };
</script>

The example above is equivalent to the following...

import Widget from './Widget.html';

const widget = new Widget({
  target: document.querySelector( '.widget-container' ),
  data: {
    foo: true,
    bar: 'static',
    baz: 'this can change'
  }
});

...except that Svelte will ensure that the value of baz is kept in sync with the value of dynamic in the parent component, and takes care of destroying the child component when the parent is destroyed.

Component names should be capitalised, following the widely-used JavaScript convention of capitalising constructor names. It's also an easy way to distinguish components from elements in your template.

Yield tags

A component can contain a {{yield}} tag, which allows the parent component to inject content:

App.html

{{#if showModal}} <Modal on:destroy='set({ showModal: false })'> <h2>Hello!</h2> <p>This is a modal dialog box. it can contain anything</p> </Modal> {{else}} <button on:click='set({ showModal: true })'>show modal</button> {{/if}} <script> import Modal from './Modal.html'; export default { components: { Modal } }; </script>

Modal.html

<div class='modal-background' on:click='destroy()'></div> <div class='modal'> {{yield}} <!-- content is injected here --> <button on:click='destroy()'>close modal</button> </div> <style> .modal-background { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.3); } .modal { position: absolute; left: 50%; top: 50%; width: calc(100% - 4em); max-width: 32em; transform: translate(-50%,-50%); padding: 1em; border-radius: 0.2em; background: white; text-align: center; } </style>

<:Self> tags

Sometimes, a component needs to embed itself recursively — for example if you have a tree-like data structure. In Svelte, that's accomplished with the <:Self> tag:

{{#if countdown > 0}}
  <p>{{countdown}}</p>
  <:Self countdown='{{countdown - 1}}'/>
{{else}}
  <p>liftoff!</p>
{{/if}}

<:Window> tags

The special <:Window> tag gives you a convenient way to declaratively add event listeners to window. Event listeners are automatically removed when the component is destroyed.

<:Window on:keydown='set({ key: event.key, keyCode: event.keyCode })'/>

{{#if key}}
  <p><kbd>{{key === ' ' ? 'Space' : key}}</kbd> (code {{keyCode}})</p>
{{else}}
  <p>click in this window and press any key</p>
{{/if}}

<style>
  kbd {
    background-color: #eee;
    border: 2px solid #f4f4f4;
    border-right-color: #ddd;
    border-bottom-color: #ddd;
    font-size: 2em;
    margin: 0 0.5em 0 0;
    padding: 0.5em 0.8em;
    font-family: Inconsolata;
  }
</style>

You can also bind to certain values — so far innerWidth, outerWidth, innerHeight, outerHeight, scrollX and scrollY:

<:Window bind:scrollY='y'/>

<div class='background'></div>
<p class='fixed'>user has scrolled {{y}} pixels</p>

<style>
  .background {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 9999px;
    background: linear-gradient(to bottom, #7db9e8 0%,#0a1d33 100%);
  }

  .fixed {
    position: fixed;
    top: 1em;
    left: 1em;
    color: white;
  }
</style>

Element directives

Directives are element or component-level instructions to Svelte. They look like attributes, except with a : character.

Event handlers

In most applications, you'll need to respond to the user's actions. In Svelte, this is done with the on:[event] directive.

<p>Count: {{count}}</p>
<button on:click='set({ count: count + 1 })'>+1</button>

When the user clicks the button, Svelte calls component.set(...) with the provided arguments. You can call any method belonging to the component (whether built-in or custom), and any data property (or computed property) that's in scope:

<p>Select a category:</p>

{{#each categories as category}}
  <button on:click='select( category )'>select {{category}}</button>
{{/each}}

<script>
  export default {
    data () {
      return {
        categories: [
          'animal',
          'vegetable',
          'mineral'
        ]
      }
    },

    methods: {
      select ( name ) {
        alert( `selected ${name}` );
      }
    }
  };
</script>

You can also access the event object in the method call:

<div on:mousemove='set({ x: event.clientX, y: event.clientY })'>
  coords: {{x}},{{y}}
</div>

<style>
  div {
    border: 1px solid purple;
    width: 100%;
    height: 100%;
  }
</style>

The target node can be referenced as this, meaning you can do this sort of thing:

<input on:focus='this.select()'>

Custom events

You can define your own custom events to handle complex user interactions like dragging and swiping. See the earlier section on custom event handlers for more information.

Component events

Events are an excellent way for nested components to communicate with their parents. Let's revisit our earlier example, but turn it into a <CategoryChooser> component:

<!-- CategoryChooser.html -->
<p>Select a category:</p>

{{#each categories as category}}
  <button on:click='fire("select", { category })'>select {{category}}</button>
{{/each}}

<script>
  export default {
    data() {
      return {
        categories: [
          'animal',
          'vegetable',
          'mineral'
        ]
      }
    }
  };
</script>

When the user clicks a button, the component will fire a select event, where the event object has a category property. Any component that nests <CategoryChooser> can listen for events like so:

<CategoryChooser on:select='playTwentyQuestions(event.category)'/>

<script>
  import CategoryChooser from './CategoryChooser.html';

  export default {
    components: {
      CategoryChooser
    },

    methods: {
      playTwentyQuestions (category) {
        // TODO implement
      }
    }
  };
</script>

Just as this in an element's event handler refers to the element itself, in a component event handler this refers to the component firing the event.

Refs

Refs are a convenient way to store a reference to particular DOM nodes or components. Declare a ref with ref:[name], and access it inside your component's methods with this.refs.[name]:

<canvas ref:canvas width='200' height='200'></canvas>

<script>
  export default {
    oncreate () {
      const canvas = this.refs.canvas;
      const ctx = canvas.getContext( '2d' );

      let destroyed = false;
      this.on( 'destroy', () => destroyed = true );

      function loop () {
        if ( destroyed ) return;
        requestAnimationFrame( loop );

        const imageData = ctx.getImageData( 0, 0, canvas.width, canvas.height );

        for ( let p = 0; p < imageData.data.length; p += 4 ) {
          const i = p / 4;
          const x = i % canvas.width;
          const y = i / canvas.height >>> 0;

          const t = window.performance.now();

          const r = 64 + ( 128 * x / canvas.width ) + ( 64 * Math.sin( t / 1000 ) );
          const g = 64 + ( 128 * y / canvas.height ) + ( 64 * Math.cos( t / 1000 ) );
          const b = 128;

          imageData.data[ p + 0 ] = r;
          imageData.data[ p + 1 ] = g;
          imageData.data[ p + 2 ] = b;
          imageData.data[ p + 3 ] = 255;
        }

        ctx.putImageData( imageData, 0, 0 );
      }

      loop();
    }
  }
</script>

Since only one element or component can occupy a given ref, don't use them in {{#each ...}} blocks. It's fine to use them in {{#if ...}} blocks however.

Two-way binding

It's currently fashionable to avoid two-way binding on the grounds that it creates all sorts of hard-to-debug problems and slows your application down, and that a one-way top-down data flow is 'easier to reason about'. This is in fact high grade nonsense. It's true that two-way binding done badly has all sorts of issues, and that very large apps benefit from the discipline of a not permitting deeply nested components to muck about with state that might affect distant parts of the app. But when used correctly, two-way binding simplifies things greatly.

Bindings are declared with the bind:[attribute] directive:

<input bind:value='name' placeholder='enter your name'>
<p>Hello {{name || 'stranger'}}!</p>

Two-way binding is not yet fully implemented. Check back soon for the full list of available bindings!

As well as DOM elements, you can bind to component data properties:

<CategoryChooser bind:category='category'/>

If the attribute and the bound property share a name, you can use this shorthand:

<CategoryChooser bind:category/>

Here is a complete example of using two way bindings with a form:

<form on:submit='handleSubmit( event )'>
  <input bind:value='test' type='text'>
  <button type='submit'>Store</button>
</form>

<script>
export default {
  methods: {
    handleSubmit: function ( event ) {
      // prevent the page from reloading
      event.preventDefault();

      var value = this.get( 'test' );
      console.log( 'value', value );
    }
  }
};
</script>

Plugins

Svelte can be extended with plugins and extra methods.

Transitions

The svelte-transitions package includes a selection of officially supported transition plugins, such as fade, fly and slide. You can include them in a component like so:

<label>
  <input type='checkbox' bind:checked='visible'> visible
</label>

{{#if visible}}
  <!-- use `in`, `out`, or `transition` (bidirectional) -->
  <div transition:fly='{y:20}'>hello!</div>
{{/if}}

<script>
  import { fly } from 'svelte-transitions';

  export default {
    transitions: { fly }
  };
</script>

Extra methods

The svelte-extras package includes a handful of methods for tweening (animating), manipulating arrays and so on.

<input bind:value='newTodo' placeholder='buy milk'>
<button on:click='push("todos", newTodo)'>add todo</button>

<ul>
  {{#each todos as todo, i}}
    <li>
      <button on:click='splice("todos", i, 1)'>x</button>
      {{todo}}
    </li>
  {{/each}}
</ul>

<style>
  ul {
    list-style: none;
    padding: 0;
  }

  li button {
    color: rgb(200,0,0);
    background: rgba(200,0,0,0.1);
    border-color: rgba(200,0,0,0.2);
    padding: 0.2em 0.5em;
  }
</style>

<script>
  import { push, splice } from 'svelte-extras';

  export default {
    data: function () {
      return {
        newTodo: '',
        todos: []
      };
    },

    methods: {
      push,
      splice
    }
  };
</script>

Static properties

Setup

In some situations, you might want to add static properties to your component constructor. For that, we use the setup property:

<p>check the console!</p>

<script>
  export default {
    setup: function(MyComponent) {
      // someone importing this component will be able
      // to access any properties or methods defined here:
      //
      //   import MyComponent from './MyComponent.html';
      //   console.log(MyComponent.ANSWER); // 42
      MyComponent.ANSWER = 42;
    },

    oncreate: function() {
      console.log('the answer is', this.constructor.ANSWER);
      console.dir(this.constructor);
    }
  };
</script>

Server-side rendering

So far, we've discussed creating Svelte components on the client, which is to say the browser. But you can also render Svelte components in Node.js. This can result in better perceived performance as it means the application starts rendering while the page is still downloading, before any JavaScript executes. It also has SEO advantages in some cases, and can be beneficial for people running older browsers that can't or won't run your JavaScript for whatever reason.

Rendering HTML

To use the server-side renderer, we must first register it. This means that when you require a component .html file, it gets intercepted by the SSR compiler:

require( 'svelte/ssr/register' );

After that, you can load components like so:

const thing = require( './components/Thing.html' );

Components have a different API in Node.js – rather than creating instances with set(...) and get(...) methods, a component is an object with a render(data) method which returns HTML (the data object is the same as you would use when instantiating a component in the browser, and is optional):

const data = { answer: 42 };
const html = thing.render( data );

Any default data, computed properties, helpers and nested components will work as expected.

The SSR compiler will generate a CommonJS module for each of your components – meaning that import and export statements are converted into their require and module.exports equivalents. If your components have non-component dependencies, they must also work as CommonJS modules in Node. If you're using ES2015 modules, we recommend reify for automatically converting them to CommonJS.

Rendering CSS

You can also render your component's (scoped) CSS, including that of any nested components:

const { css, components } = thing.renderCss();

You could put the resulting css in a separate stylesheet, or include them in the page inside a <style> tag. If you do this, you will probably want to prevent the client-side compiler from including the CSS again. For svelte-cli, use the --no-css flag. In build tool integrations like rollup-plugin-svelte, pass the css: false option.

The components array contains an object for each nested component that contains styles, allowing you to dedupe styles across multiple top-level components. Most of the time, you won't need to do this.

Advanced

Keyed each blocks

Associating a key with a block allows Svelte to be smarter about how it adds and removes items to and from a list. To do so, add @key to the end of the opening tag for the each block, where key is some property that uniquely identifies each member of the list:

{{#each people as person @name}}
  <div>{{person.name}}</div>
{{/each}}

It's easier to show the effect of this than to describe it. Open the following example in the REPL:

<button on:click='update()'>update</button>

<section>
  <h2>Keyed</h2>
  {{#each people as person @name}}
    <div transition:slide>{{person.name}}</div>
  {{/each}}
</section>

<section>
  <h2>Non-keyed</h2>
  {{#each people as person}}
    <div transition:slide>{{person.name}}</div>
  {{/each}}
</section>

<style>
  button {
    display: block;
  }

  section {
    width: 20em;
    float: left;
  }
</style>

<script>
  import { slide } from 'svelte-transitions';

  var people = ['Alice', 'Barry', 'Cecilia', 'Douglas', 'Eleanor', 'Felix', 'Grace', 'Horatio', 'Isabelle'];

  function random() {
    return people
      .filter(() => Math.random() < 0.5)
      .map(name => ({ name }))
  }

  export default {
    data() {
      return { people: random() };
    },

    methods: {
      update() {
        this.set({ people: random() });
      }
    },

    transitions: { slide }
  };
</script>

TODO...

This documentation is still a work-in-progress, like Svelte itself. If there are particular things that are missing or could be improved, then please raise an issue on GitHub!