INTRODUCTION
Today in this blog, you’ll learn how to create a Todo List App in HTML CSS & JavaScript. In this to-do app, you can easily add or delete your task. There are filters button too that helps you to filter the tasks. The tasks you added to this todo app will be stored in the browser's local storage, it won’t be removed on page refresh or tab close.
If you want to see what this todo app looks like and how it works then you can watch a demo or full video tutorial of the Todo List App in JavaScript.
Video Tutorial of To-Do List App
In the above video, you have seen the demo of this To-do App and how I created it using HTML CSS & JavaScript. I hope you liked this to-do app and its several features. I can also understand if you’re a beginner in JavaScript and didn’t create any todo-related projects before then these to-do codes might be difficult to understand for you.
If you liked this to-do and want to get source codes or files, you can easily copy or download them from the bottom of this page.
You might like this:
Prerequisites
We suggest you have basic knowledge of HTML and CSS before moving on to the tutorial. Even though it is a simple tutorial, it will help if you already know the most basic concepts. We are using Visual Studio Code as the text editor for this tutorial. It is a simple, powerful text editor and supports many languages, including HTML, CSS, and JavaScript. (Download Visual Studio Code)
Todo List App in JavaScript [Source Codes]
In order to create a simple to-do list, we have to follow the following four steps:
Step 1: Add HTML
Create an HTML file with the name index.html and paste the given codes into your HTML file. Remember, you’ve to create a file with a .html extension.
<!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>To-DO LIST</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<body>
<div class="wrapper">
<div class="task-input">
<ion-icon name="create-outline"></ion-icon>
<input type="text" placeholder="Add a New Task + Enter">
</div>
<div class="controls">
<div class="filters">
<span class="active" id="all">All</span>
<span id="pending">Pending</span>
<span id="completed">Completed</span>
</div>
<button class="clear-btn">Clear All</button>
</div>
<ul class="task-box"></ul>
</div>
</body>
<script src="script.js"></script>
</html>
Explanation
- We make a div that acts as a container for our to-do list.
- We make a div for the new task in which the user writes the name of the task.
- We create a div for the written tasks.
- We create a div for our todo filters
- And at the end, we make a "Clear All" Button.
Step 2: Add CSS
Create a CSS file with the name style.css and paste the given codes into your CSS file. Remember, you’ve to create a file with a .css extension.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
width: 100%;
height: 100vh;
overflow: hidden;
background: linear-gradient(135deg, #f5af19, #f12711);
}
::selection {
color: #fff;
background: #f12711;
}
.wrapper {
max-width: 405px;
background: #fff;
margin: 137px auto;
border-radius: 7px;
padding: 28px 0 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.task-input {
position: relative;
height: 52px;
padding: 0 25px;
}
.task-input ion-icon {
position: absolute;
top: 50%;
color: #999;
font-size: 25px;
transform: translate(17px, -50%);
}
.task-input input {
height: 100%;
width: 100%;
outline: none;
font-size: 18px;
border-radius: 5px;
padding: 0 20px 0 53px;
border: 1px solid #999;
}
.task-input input:focus,
.task-input input.active {
padding-left: 52px;
border: 2px solid #f12711;
}
.task-input input::placeholder {
color: #bfbfbf;
}
.controls,
li {
display: flex;
align-items: center;
justify-content: space-between;
}
.controls {
padding: 18px 25px;
border-bottom: 1px solid #ccc;
}
.filters span {
margin: 0 8px;
font-size: 17px;
color: #444444;
cursor: pointer;
}
.filters span:first-child {
margin-left: 0;
}
.filters span.active {
color: #f12711;
}
.clear-btn {
border: none;
opacity: 0.6;
outline: none;
color: #fff;
cursor: pointer;
font-size: 13px;
padding: 7px 13px;
border-radius: 4px;
letter-spacing: 0.3px;
pointer-events: none;
transition: transform 0.25s ease;
background: linear-gradient(135deg, #f5af19 0%, #f12711 100%);
}
.clear-btn.active {
opacity: 0.9;
pointer-events: auto;
}
.clear-btn:active {
transform: scale(0.93);
}
.task-box {
margin-top: 20px;
margin-right: 5px;
padding: 0 20px 10px 25px;
}
.task-box.overflow {
overflow-y: auto;
max-height: 300px;
}
.task-box::-webkit-scrollbar {
width: 5px;
}
.task-box::-webkit-scrollbar-track {
background: #f12711;
border-radius: 25px;
}
.task-box::-webkit-scrollbar-thumb {
background: #e6e6e6;
border-radius: 25px;
}
.task-box .task {
list-style: none;
font-size: 17px;
margin-bottom: 18px;
padding-bottom: 16px;
align-items: flex-start;
border-bottom: 1px solid #ccc;
}
.task-box .task:last-child {
margin-bottom: 0;
border-bottom: 0;
padding-bottom: 0;
}
.task-box .task label {
display: flex;
align-items: flex-start;
}
.task label input {
margin-top: 7px;
accent-color: #f12711;
}
.task label p {
user-select: none;
margin-left: 12px;
word-wrap: break-word;
}
.task label p.checked {
text-decoration: line-through;
}
.task-box .settings {
position: relative;
}
.settings :where(i, li) {
cursor: pointer;
}
.settings .task-menu {
position: absolute;
right: -5px;
bottom: -65px;
padding: 5px 0;
background: #fff;
border-radius: 4px;
transform: scale(0);
transform-origin: top right;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.15);
transition: transform 0.2s ease;
z-index: 10;
}
.task-box .task:last-child .task-menu {
bottom: 0;
transform-origin: bottom right;
}
.task-box .task:first-child .task-menu {
bottom: -65px;
transform-origin: top right;
}
.task-menu.show {
transform: scale(1);
}
.task-menu li {
height: 25px;
font-size: 16px;
margin-bottom: 2px;
padding: 17px 15px;
cursor: pointer;
justify-content: flex-start;
}
.task-menu li:last-child {
margin-bottom: 0;
}
.settings li:hover {
background: #f5f5f5;
}
.settings li i {
padding-right: 8px;
}
@media (max-width: 400px) {
body {
padding: 0 10px;
}
.wrapper {
padding: 20px 0;
}
.filters span {
margin: 0 5px;
}
.task-input {
padding: 0 20px;
}
.controls {
padding: 18px 20px;
}
.task-box {
margin-top: 20px;
margin-right: 5px;
padding: 0 15px 10px 20px;
}
.task label input {
margin-top: 4px;
}
}
Explanation
- We add the styling for the container.
- We add the styling for the tasks input field and the add “Task” button.
- We add the styling for the tasks which we have added.
Step 3: Add JavaScript
Create a JavaScript file with the name script.js and paste the given codes into your JavaScript file. Remember, you’ve to create a file with a .js extension.
const taskInput = document.querySelector(".task-input input"),
filters = document.querySelectorAll(".filters span"),
clearAll = document.querySelector(".clear-btn"),
taskBox = document.querySelector(".task-box");
let editId,
isEditTask = false,
todos = JSON.parse(localStorage.getItem("todo-list"));
filters.forEach((btn) => {
btn.addEventListener("click", () => {
document.querySelector("span.active").classList.remove("active");
btn.classList.add("active");
showTodo(btn.id);
});
});
showTodo("all");
function showTodo(filter) {
let liTag = "";
if (todos) {
todos.forEach((todo, id) => {
let completed = todo.status == "completed" ? "checked" : "";
if (filter == todo.status || filter == "all") {
liTag += `<li class="task">
<label for="${id}">
<input onclick="updateStatus(this)" type="checkbox" id="${id}" ${completed}>
<p class="${completed}">${todo.name}</p>
</label>
<div class="settings">
<i onclick="showMenu(this)" class="uil uil-ellipsis-h"></i>
<ul class="task-menu">
<li onclick='editTask(${id}, "${todo.name}")'><i class="uil uil-pen"></i>Edit</li>
<li onclick='deleteTask(${id}, "${filter}")'><i class="uil uil-trash"></i>Delete</li>
</ul>
</div>
</li>`;
}
});
}
taskBox.innerHTML = liTag || `<span>You don't have any task here</span>`;
let checkTask = taskBox.querySelectorAll(".task");
!checkTask.length
? clearAll.classList.remove("active")
: clearAll.classList.add("active");
taskBox.offsetHeight >= 300
? taskBox.classList.add("overflow")
: taskBox.classList.remove("overflow");
}
function showMenu(selectedTask) {
let menuDiv = selectedTask.parentElement.lastElementChild;
menuDiv.classList.add("show");
document.addEventListener("click", (e) => {
if (e.target.tagName != "I" || e.target != selectedTask) {
menuDiv.classList.remove("show");
}
});
}
function updateStatus(selectedTask) {
let taskName = selectedTask.parentElement.lastElementChild;
if (selectedTask.checked) {
taskName.classList.add("checked");
todos[selectedTask.id].status = "completed";
} else {
taskName.classList.remove("checked");
todos[selectedTask.id].status = "pending";
}
localStorage.setItem("todo-list", JSON.stringify(todos));
}
function editTask(taskId, textName) {
editId = taskId;
isEditTask = true;
taskInput.value = textName;
taskInput.focus();
taskInput.classList.add("active");
}
function deleteTask(deleteId, filter) {
isEditTask = false;
todos.splice(deleteId, 1);
localStorage.setItem("todo-list", JSON.stringify(todos));
showTodo(filter);
}
clearAll.addEventListener("click", () => {
isEditTask = false;
todos.splice(0, todos.length);
localStorage.setItem("todo-list", JSON.stringify(todos));
showTodo();
});
taskInput.addEventListener("keyup", (e) => {
let userTask = taskInput.value.trim();
if (e.key == "Enter" && userTask) {
if (!isEditTask) {
todos = !todos ? [] : todos;
let taskInfo = { name: userTask, status: "pending" };
todos.push(taskInfo);
} else {
isEditTask = false;
todos[editId].name = userTask;
}
taskInput.value = "";
localStorage.setItem("todo-list", JSON.stringify(todos));
showTodo(document.querySelector("span.active").id);
}
});
Explanation
We write a function that states that if a user doesn’t enter any task and presses the “Add” button, then an alert message is generated which states that enter the task.
If the user enters a task, then we have to decide what to do with the task. We use the inner HTML to display all the information on the web page.
We add a “Delete” button which can be found after every task
Live Demo
That’s all, now you’ve successfully created a Todo List App in HTML CSS & JavaScript. If your code doesn’t work or you’ve faced any problems, please download the Source Code files from the given link. It’s free and a .zip file will be downloaded then you’ve to extract it.
GitHub Repository[Source Code]
That’s all! Hopefully, you have successfully integrated the code of these HTML To-Do List App. If you have any questions or suggestions, let me know by comment below.