
Posted on • Originally published atblog.avneesh.tech
How to Build a Todo app with Svelte!
Demo
Setup
Create app
npx degit sveltejs/template svelte-todo-app
cd into the folder-
cd svelte-todo-app
Install dependencies
npm install # npmyarn install # yarn
Start app
npm run dev # npmyarn dev # yarn
Cleanup
I don't want the default stylings, so I will replace the stylings inglobals.css
with this-
* { margin: 0;}body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;}code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;}
Building the container
InApp. svelte
let's create the starter code for our app.
<script></script><main></main><style> .container { display: flex; flex-direction: column; align-items: center; min-height: 90vh; background: #222e50 url(https://images.unsplash.com/photo-1579546929518-9e396f3cc809?ixid=MXwxMjA3fDB8MHxzZWFyY2h8N3x8Z3JhZGllbnR8ZW58MHx8MHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60) no-repeat; background-size: cover; padding-top: 10vh; }</style>
Building the form to submit Todos
Inside our main container, add a form component with input and button-
<main> <div> <form on:submit|preventDefault={addTodo}> <input bind:value={newItem} type="task" placeholder="Enter Todo" /> <button>+</button> </form> </div></main>
We need to create the following things now-
A variable to store the input value
A
addTodo
function for adding the todos.
So in the script tag add the following-
let newItem = ""; let todoList = []; function addTodo() { if (newItem !== "") { todoList = [ ...todoList, { task: newItem, completed: false, }, ]; newItem = ""; } console.log(todoList); }
Styling
Now let's style our submit button and the input. Inside the styles, tag add this-
.todos__input { background-color: inherit; border: none; box-shadow: none; text-decoration: none; font-size: 1.2rem; border-bottom: 1px solid black; margin-top: 15px; outline: none; width: 500px; } .todos__button { background-color: inherit; border: none; box-shadow: none; font-size: 1.2rem; cursor: pointer; }
If we now add an item, it will add the item to the list and console log it.
Rendering the todos
In React like we have a map function, we do it through#each
in Svelte
{#each todoList as item, index} <div> <span>{item.task}</span> </div> {/each}
Styling the todos
.todo { display: flex; padding: 20px; border-radius: 20px; box-shadow: 0 0 15px rgb(0 0 0 / 20%); background-color: hsla(0, 0%, 100%, 0.2); -webkit-backdrop-filter: blur(25px); backdrop-filter: blur(25px); width: inherit; margin-top: 15px; font-size: 1.2rem; justify-content: space-between; align-items: center; }
This will give the todos a glassmorphic look 🤩
Adding a header for the todos
The to-do list and the inputs look kinda clumsy, so let's add a header there-
After the form component add this h2 tag-
<h2>Todos</h2>
The stylings for this header-
.todos__listHeader { text-align: center; padding: 20px; border-radius: 20px; box-shadow: 0 0 15px rgb(0 0 0 / 20%); background-color: hsla(0, 0%, 100%, 0.2); -webkit-backdrop-filter: blur(25px); backdrop-filter: blur(25px); margin: 15px 0px 25px 0px; font-size: 1.2rem; }
Now we have got a pretty good separation there.
Creating the complete and delete functionality
We are going to use icons for delete and complete, so let's get the icons first.
- Create
Icons. svelte
file in the src directory. Add the following piece of code, for the icons. Feel free to change the icons :) -
<script> export let name; export let width = "1.5rem"; export let height = "1.5rem"; export let focusable = false; let icons = [ { box: 24, name: "check-mark", svg: `<svg focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M19.77 4.93l1.4 1.4L8.43 19.07l-5.6-5.6 1.4-1.4 4.2 4.2L19.77 4.93m0-2.83L8.43 13.44l-4.2-4.2L0 13.47l8.43 8.43L24 6.33 19.77 2.1z"></path></svg>`, }, { box: 32, name: "delete", svg: `<svg focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM8 9h8v10H8V9zm7.5-5l-1-1h-5l-1 1H5v2h14V4h-3.5z"></path></svg>`, }, ]; let displayIcon = icons.find((e) => e.name === name);</script><svg class={$$props.class} {focusable} {width} {height} viewBox="0 0 {displayIcon.box} {displayIcon.box}">{@html displayIcon.svg}</svg>
Show the icons
Inside the todo, I will add a div with two buttons that have the icons as follows-
{#each todoList as item, index} <div> <span>{item.task}</span> <div> <button on:click={() => (item.completed = !item.completed)} > <Icons name="check-mark" /> </button> <button on:click={() => removeFromList(index)}> <Icons name="delete" /> </button> </div> </div>{/each}
Import the icons like this-
import Icons from "./Icons.svelte";
Creating the delete function-
function removeFromList(index) { todoList.splice(index, 1); todoList = todoList; }
Styling the buttons
Add the following styles to get a beautiful icon button-
.icon__button { background-color: transparent; border: none; box-shadow: none; font-size: 1.2rem; cursor: pointer; color: rgba(0, 0, 0, 0.54); } .icon { background: rgba(0, 0, 0, 0.54); }
Striking the Text
Add this optional class to the item. task span, so if the item is completed then it will add the class-
<span class={`todo__text ${item.completed ? "todo__checked--strike" : ""}`} >{item.task}</span >
Now, we need to add the styles to strike it-
.todo__checked--strike { text-decoration: line-through; }
This function takes an argument ofindex
and splices the todoList to remove the item.
We have successfully built a to-do app in Svelte! 🥳🎉
To extend your knowledge about svelte check out this video byJames Q Quick where he will show you how to create a todo app with Sveltekit and tailwind CSS!
Useful links
Top comments(7)

Are your todo' lost when you close the app or do they persist until you open the app again?

- Email
- LocationIndia
- Joined
Yeah, I haven't implemented localstorage in this one :)

If I remember correctly (and I dont always do) the stock demo app you get when you
npm init svelte@next
Has a persistent todo list example you may want to take some inspiration from.
Looks good other wise
Happy coding

- Email
- LocationIndia
- Joined
Um, I didn't know you can generate like that and I know how to add that feature but wanted to keep this tutorial simple. Thanks for understanding :)

👍

- Email
- LocationIndia
- Joined
Thanks!
For further actions, you may consider blocking this person and/orreporting abuse