Create a Basic Svelte Siteđź“„đź“„
First published on .
I recently used SvelteJS to create a portfolio of websites I’ve built. Right now there’s only two websites listed, but I’m sure it will expand over time. The process of writing the website was fun — figuring out the syntax of Svelte, using the lovely transition and animation libraries, and playing with event handlers. Here’s a quick guide for how you can get started with Svelte.
What is Svelte?
Svelte is a tool for building fast web applications. It’s a bit similar to other frontend frameworks like React and Vue. Like React, Svelte constructs components, but unlike React which does its work in the browser at run time, Svelte compiles your app into optimized Javascript code.
I found that writing Svelte code is fun — it’s more like writing vanilla HTML or CSS than writing React — and animations and transitions have first class support.
Creating a Project with Svelte 3
There is a template that you can use as a starting point to create your Svelte project. In your terminal run:
npx degit sveltejs/template my-svelte-project
This will use npx to run degit to create your svelte project.
Next go into the directory and run npm install.
cd my-svelte-project && npm install
Now that all the packages are installed you can start up the development server using npm run dev
and see your website at http://localhost:5000. Your Svelte component is stored in the file src/App.svelte
, although you can easily create additional components and import them into App.svelte
.
Basic Svelte Structure
A svelte file typically has a script
tag, a style
tag, and the svelte component. The script
tags are where the brains of your Svelte component go — variable and function declarations. The style
tag is contains the CSS to style your component. And finally there’s the svelte component, which for the most part you compose like you would with HTML or JSX, but there are some exceptions.
The most obvious exception are the if block, each block, and await block which are written in-line in the svelte component.
If block
The if block displays certain components conditionally.
{#if expression}
<div>This div is displayed conditionally.</div>
{:else}
<div>Or this will be displayed</div>
{/if}
Each block
The each block cycles through an array and displays code a certain way.
<ul>
{#each items as item}
<li>{item.name}</li>
{/each}
</ul>
Await block
The await block waits for asynchronous code to return and then displays content.
{#await promise}
<p>Waiting for the promise</p>
{:then value}
<p>The value is {value}</p>
{/await}
Svelte Transitions & Animations
The real star of my experience with Svelte has been the transitions and animations.
Transitions have first class support in Svelte, you just import the transition from svelte and attach it to the element you want to transition. For my website I created a Bio
component so that if my name is clicked a short introduction will drop down. Implementing this in Svelte was straightforward. Here’s my Bio
component with the styles removed:
<script>
import { slide } from "svelte/transition";
let visible = false;
let symbol = "â–˝";
export let intro;
</script>
<style>
...
</style>
<div class="bio">
<span class="name" on:click={() => (visible = !visible)}>
<h1>Daniel Chapman</h1>
<span class="symbol">{visible ? 'x' : 'â–˝'}</span>
</span>
{#if visible}
<div class="about" transition:slide>
<h2>About Me</h2>
<div class="intro">{intro}</div>
</div>
{/if}
</div>
You’ll see a few things here. First the on:click
handler which toggles the visible
variable. You’ll also see that there’s an if block whose contents will only display if visible
is true. And finally in the div
with the “about” class you’ll see the transition:slide
attribute; this tells Svelte how to transition the element when it gets attached to or removed from the DOM — in other words whenever my name is clicked.
This is where the magic of Svelte started shining through for me. All I hd to do to add a fancy slide transition was to add the transition:slide
attribute to a component.
Animations are a little trickier. I wanted a hover effect on the website cards I created so I created on:mouseenter
and on:mouseleave
handlers that use Svelte’s tweened
function from svelte/motion
. tweened
is a function that starts at an initial value, then when you call set(newvalue)
, it gradually moves from its initial value to the new value taking into consideration a duration
in milliseconds and an easing
function that effects how the value is incremented. I used this in combination with a style attribute to gradually animate CSS box-shadow
when the mouse hovers over a website card.
The relevant code for the animation is below.
<script>
export let technologies = [];
export let code = "";
export let title = "There was no Title";
export let description = "There was no Description";
export let link;
export let image = "";
let hovered = false;
import { onMount } from "svelte";
import { fade, slide } from "svelte/transition";
import { tweened } from "svelte/motion";
import { cubicOut } from "svelte/easing";
const shadow = tweened(0, { duration: 500, easing: cubicOut });
function handleClick() {
window.location = link;
}
function handleMouseEnter() {
shadow.set(1);
hovered = true;
}
function handleMouseLeave() {
shadow.set(0);
hovered = false;
}
let mounted = false;
onMount(() => (mounted = true));
</script>
At the top of the code block I define a tweened function called shadow
which will gets set to 1 in handleMouseEnter()
and 0 in handleMouseLeave()
You’ll also see the values on:touchstart
and on:touchend
, I discovered that these handle finger presses, so I set them to the equivalent mouse handler.. It does this over the period of 1/2 a second and uses a cubic easing function (cubicOut
) Now let’s continue to look at the Svelte component below:
{#if mounted}
<div
on:click={handleClick}
on:mouseenter={handleMouseEnter}
on:touchstart={handleMouseEnter}
on:mouseleave={handleMouseLeave}
on:touchend={handleMouseLeave}
transition:slide={{ delay: 200 }}
style="box-shadow: {$shadow * 30}px {$shadow * 15}px #925c77, {$shadow * 45}px
{$shadow * 21}px #75B9BE, {$shadow * 60}px {$shadow * 30}px #7297A6;"
class="site">
<h2
class="title"
transition:fade={{ delay: 250 }}
style="text-decoration: {hovered ? 'underline' : 'none'};">
<a href={link}>{title}</a>
</h2>
<img src={image} alt="A screenshot of {title}" />
<div class="description" transition:fade={{ delay: 500 }}>
{description}
</div>
<div class="code">
<ul>
{#each technologies as technology}
<li>{technology}</li>
{/each}
</ul>
<a href={code}>Source Code</a>
</div>
</div>
{/if}
In the top-level div you’ll see there is a style tag. Animating the CSS in Svelte was a simple matter of using the style tag, and because Svelte allows JS within the curly brackets multiplying the shadow
variable (which moves from 0 to 1 when the mouse is hovered, and from 1 to 0 when the mouse is removed.) by different values to create the triple-layered shadow effect that you can see on the site.
Conclusion
All in all it took less than a weekend from the moment I started learning Svelte watching this 26 minute Egghead collection to when I finished the rough draft of my Svelte website. It might not have taken long, but it was long enough to show me that Svelte is a unique, fun language with powerful functionality.
The code for my website is open source and you are welcome to browse it, copy it, and tinker with it.
Other things to read
- Hypertext WritingEvery medium has its strengths. There are considerable strengths inherent to a digital, web-based, way of thinking -- first and foremost is the sheer amount of interactivity and connections you can make.
- How I used Twitter as a CMSHow I built a website that uses the Twitter API to fetch data from tweets I liked to create a grid of colors.
- Using Dendron and Gatsby Together 🌲How I integrated my Dendron repository and my Gatsby.js website.