Create To-do List using Vanilla JavaScript
Tags: html, css, javascript, tutorial
Published: 2021-06-30 15:47:15

It's a simple To-do app. As a beginner, creating these features like DOM manipulations, animations and dark theme feature was challenging for me. So let's see how I created this and what I've learned from it.

#####Prerequisite Knowledge
Basics of HTML, CSS and JS (specially DOM Manipulations)

#####What I've Learned

+ DOM Manipulation
+ Classlist 
+ ChildNodes
+ Forms
+ Changing Themes 

---
##Let's Start

We will create this project step by step.
![Features Planning](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoxekts6n1jm4icjefrn.png)

### 1. Brainstorming

First you have to plan the features of your to-do app. You can use any software to plan your project or just a pen and paper. I generally prefer to plan everything in Notion.

![Features Planning](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgiwfp7c5ryquhrz57xo.png)
---
---

### 2. Sketching

Make a simple sketch of To-do app which contains all your decided features.

![Sketching](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2yuuupzp8s1ra7yppj0l.png)
---
---

### 3. Prototype

Make a prototype of your app using previous sketch. You can also follow these steps to design your app.

+ Make a color palette of 3 colors.
+ Choose the typeface.
+ Collect SVG icons
+ Start designing
+ Design the Dark theme

![Xd Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1djcwj1cpbxr6u1yfl7.png)
---
---


### 4. Setup Project Environment

In this step, setup the directories and create files for your project.

![Setup Environment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0lpsqdcv32qperbsiyix.png)
---
---


### 5. Create HTML structure

Open your `index.html` file and create the html structure. Don't forget to link your CSS and Js file with index.html.


######Refrence code is given below.


```HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>TODO :: By karan Kumar</title>

    <link rel="stylesheet" href="style.css" />
    <script src="script.js" defer></script>
</head>

<body>
    <div class="container task_list_empty">
        <header>
            <div class="theme_toogle">
                <button class="theme_toogle_btn"></button>
            </div>
            <span class="heading">My Day</span>
        </header>
        <section class="tasks">
            <ul id="tasksList"></ul>
        </section>
        <footer>
            <form id="new_task_form">
                <input type="text" name="new_task_input" id="new_task_input" placeholder="Create New Task" value="" />
                <button id="new_task_input_btn" type="submit"></button>
            </form>
        </footer>
    </div>
</body>

</html>
```
---


### 6. Add CSS Styling

Open your `style.css` file to style the to-do app. Follow these steps to style your to-do.

  + Set root variables
  + Define container layouts
  + Set hover effects 
  + Style input placeholder using pseudo classes.
  + Add Media queries

######Refrence code is given below.

```CSS
:root {
    --primary-color: white;
    --secondary-color: #1E1E1E;
    --text-color: black;
    --task-color: white;
    --footer-color: #1E1E1E;
    --theme-btn: url('assets/Dark-theme-btn.svg');
    --container-bg: url('./assets/Light-empty.svg');
    --complete-icon: url('assets/complete.svg');
    --filter: none;
    --theme-transition: 0s;

}

* {
    font-family: "Times New Roman";
    outline: none;
}

body {
    display: flex;
    min-height: 100vh;
    justify-content: center;
    align-items: center;
    overflow: hidden;

}

.container {
    position: relative;
    border: 4px var(--footer-color) solid;
    padding: 30px;
    display: flex;
    flex-direction: column;
    width: 300px;
    height: 80vh;
    border-radius: 20px;
    overflow: hidden;
    background: var(--primary-color);
    transition: var(--theme-transition);
}

header {
    display: flex;
    flex-direction: column;
}

.heading {
    font-weight: 900;
    color: var(--text-color);
}

.theme_toogle {
    text-align: right;
    margin-right: -15px;

}

.theme_toogle_btn {
    min-width: 30px;
    min-height: 30px;
    background-color: transparent;
    border: none;
    outline: none;
    background-image: var(--theme-btn);
    background-repeat: no-repeat;
    background-size: 80%;
    background-position: center;
    padding: 20px;
    cursor: pointer;
}

.theme_toogle_btn:hover {
    background-size: 85%;
    transition: 0.5s;
    transform: rotate(90deg);
}

.heading {
    font-size: 30px;
}

.tasks {
    margin: 20px 0px;
    overflow: hidden;
    padding-right: 15p;
}

#tasksList {
    padding: 0px;
}

.task_list_empty {
    transition: 0s;
    background-position: center;
    background-size: 50%;
    background-repeat: no-repeat;
    background-image: var(--container-bg);

}

.task_item {
    list-style-type: none;
    border: 1px var(--secondary-color) solid;
    padding: 10px;
    display: flex;
    flex-direction: row;
    align-items: center;
    border-radius: 7px;
    margin-bottom: 20px;
    background-color: var(--task-color);
    color: var(--text-color);
}

.task_item:hover {
    transition: 0.5s;
    /* border: 1px rgba(148, 148, 148, 0.63) solid; */
    cursor: pointer;
    background-color:rgba(226, 226, 226, 0.192);

}

.task_check_btn {
    width: 10px;
    height: 10px;
    margin-right: 16px;
    padding: 3px;
    border: 2px var(--secondary-color) solid;
    /* color: var(--primary-color); */
    background-position: center;
    background-size: contain;
    border-radius: 50%;
    border: 2px grey solid;
    cursor: pointer;
}

.task_check_btn:hover {
    background-image: url('assets/complete.svg');
    /* opacity: 0.5; */
    filter: var(--filter);

}

.task_bio {
    font-size: 18px;
}



.task-completed {
    transition: 0.5s;
    transform: scale(90%);
    text-decoration: line-through;
    color: rgb(150, 150, 150);
    opacity: 0;

}

footer {
    position: absolute;
    bottom: 0px;
    padding: 15px 10px;
    min-width: 100%;
    background-color: var(--footer-color);
    left: 0px;
    border: 5px var(--footer-color) solid;
}

footer form {
    display: flex;
    flex-direction: row;
    align-content: center;
}

#new_task_input {
    min-width: 250px;
    margin-right: 40px;
    font-size: 20px;
    color: white;
    background-color: transparent;
    border: none;
    border-bottom: 1px rgba(255, 255, 255, 0.267) solid;
}

#new_task_input::placeholder {
    color: rgba(255, 255, 255, 0.589);
    font-size: 20px;
    font-family: "Times New Roman";
}

#new_task_input_btn {
    width: 30px;
    height: 30px;
    background-color: transparent;
    border: none;
    background-image: url('./assets/new.svg');
    background-repeat: no-repeat;
    background-size: 80%;
    cursor: pointer;
}

.taskCompleted {
    visibility: hidden;
}

@media screen and (max-width : 600px) {

    body {
        margin: 0px;
        padding: 0px;
        align-items: flex-start;
        height: 100vh;
        background-color: var(--bg-color);

    }

    .theme_toogle {
        margin-top: 30px;

    }

    .container {
        border: none;
        border-radius: 0px;
        width: 100%;
        height: 93vh;
        padding: 0px 20px;
    }

    #new_task_input {
        margin-right: 20px;
    }
}

```
---


### 7. Add JavaScript Functionality

Before starting any JS code, first you have to plan the working of your To-do App 
######Plan the working of to-do app
![To-do Working](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdpqphu9dvc8mmrryqe3.png)

When user enter a new task in input and submit the form the task input value will go to a function , which creates a task element with checkbox using task input value. then add another function, which remove the task item  when checkbox get checked.

Open your `script.js` file and style the to-do app. Follow these steps to add JS Functionality.

######Refrence code is given below.

```JS
// Variables
var root = document.querySelector(':root')
var container = document.querySelector('.container');
var newTaskInput = document.getElementById('new_task_input')
var taskform = document.getElementById('new_task_form');
var tasksList = document.getElementById('tasksList');
var taskBtns = document.querySelectorAll('.task_check_btn');
var themeBtn = document.querySelector('.theme_toogle_btn');
// Do this when we submit the form
taskform.addEventListener('submit', function (e) {

    e.preventDefault();
    var newtaskInputValue = taskform.elements.new_task_input;


    addTask(newtaskInputValue.value)

    // Reset input value to empty
    newtaskInputValue.value = '';
    container.classList.remove('task_list_empty')


})

// To  add task in List
function addTask(newTask) {

    // Create li element and set its class
    const newTaskItem = document.createElement('li');
    newTaskItem.setAttribute('class', 'task_item');

    // Create checkbox  element and set its type and  class 

    const newCheckBtn = document.createElement('div');
    newCheckBtn.setAttribute('class', 'task_check_btn')

    // Create span  element and set its class and add new task input
    const newTaskBio = document.createElement('span');
    newTaskBio.setAttribute('class', 'task_bio')
    // Put value of input in it
    newTaskBio.innerText = newTask; // putting value of input in the li

    // append (insert) li tag in Ul
    tasksList.appendChild(newTaskItem)
    // append (insert) checkbox in li
    newTaskItem.appendChild(newCheckBtn)

    // append (insert) newtask in li
    newTaskItem.appendChild(newTaskBio)

    // Run this function when task is completed or checkbox is checked
    onTaskComplete(newCheckBtn)

}

// To remove the completed task
function onTaskComplete(btns) {

    btns.addEventListener('click', function (e) {
        var parent = e.toElement.parentElement;
        parent.classList.add('task-completed'); // To slide out the task to the right
        // Now we delete that tast which we have slided out
        setTimeout(() => {
            // Removing Parent Element of checkobx which is Li in 0.5 s
            parent.remove();
        }, 400);


        if (tasksList.childNodes.length == 1) {
            setTimeout(() => {
                container.classList.add('task_list_empty')

            }, 800);
        }

    })


}


// Dark mode

themeBtn.addEventListener('click', function () {


    var darkTheme = themeBtn.classList.toggle('dark')

    if (darkTheme) {

        root.style.setProperty('--theme-transition', '1s')
        root.style.setProperty('--primary-color', '#1E1E1E')
        root.style.setProperty('--secondary-color', '#3B3B3B')
        root.style.setProperty('--text-color', '#EAEAEA')
        root.style.setProperty('--task-color', '#3B3B3B')
        root.style.setProperty('--footer-color', '#1E1E1E')
        root.style.setProperty('--theme-btn', `url('assets/Light-theme-btn.svg')`)
        root.style.setProperty('--container-bg', `url('./assets/Dark-empty.svg')`)
        root.style.setProperty('--filter', 'invert()')

    } else {
        root.style.setProperty('transition', '1s')
        root.style.setProperty('--primary-color', 'white')
        root.style.setProperty('--secondary-color', '#1E1E1E')
        root.style.setProperty('--text-color', 'black')
        root.style.setProperty('--task-color', 'white')
        root.style.setProperty('--footer-color', '#1E1E1E')
        root.style.setProperty('--theme-btn', `url('assets/Dark-theme-btn.svg')`)
        root.style.setProperty('--container-bg', `url('./assets/Light-empty.svg')`)
    }
})

```

---

## [View Demo](https://karan-kmr.github.io/To-Do-List/)

[![Project Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bcpn0v2l50l5u38vwens.gif 
 "Click To View Demo")](https://karan-kmr.github.io/To-Do-List/)


[![Edit To-do List](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/to-do-list-vshkg?fontsize=14&hidenavigation=1&theme=dark)
---

###Source Code

 {% github karan-kmr/To-Do-List no-readme %}

---
### Find Me on Instagram
 
 [![@karancodes Instagram Profile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38dkuuvtufkyoxggelag.png 
 "Click to view Profile")](https://bit.ly/3h4UivA)