When we learn HTML, CSS, and JavaScript, we often build a to-do list project to better practice and understand these languages. During interviews, interviewers often ask candidates to create a to-do list because it effectively showcases their proficiency in essential web development skills such as manipulating the web page's structure (DOM manipulation), managing user interactions (event handling), and storing data locally. This project shows how well the candidate can work with these important aspects of web development.
So, in today's article, we'll build a complete to-do list app where users can add, edit, mark tasks as done, and remove them. Additionally, we'll ensure that tasks are saved even after closing the browser by using local storage.
So let's get started.
Table of contents:
- How to Build Logic for This Project
- Project Setup
- HTML Structure
- JavaScript Functionality
- Styling with CSS
- Questions and answers
How to Build Logic for This Project
When building the logic for this to-do list application, we must consider how each functionality should work. Here’s a step-by-step approach:
- Add Task: Users can add new tasks to the list by clicking the 'Add' button.
- Edit Task: Users can modify existing tasks by clicking an edit button and updating the task text as needed.
- Complete Task: Users can mark tasks as complete by clicking a checkbox associated with each task.
- Delete Task: Users can remove tasks from the list by clicking a delete button, which allows them to delete tasks as needed.
- Local Storage: Tasks are stored locally, allowing them to persist even after refreshing or closing the browser, ensuring your data is always saved between sessions.
Now that we understand how each feature will operate in our to-do list application, let's proceed to set up the project.
Project Setup
Before we start coding, let's set up our project. Create a new folder for your project and add these three files: index.html, style.css, and script.js.
HTML Structure
With this HTML file, we will create the structure for our to-do list application, including a form to add new tasks and a list to display them. So include this code in your index.html file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To-Do List</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>My To-Do List</h1>
<input type="text" id="new-todo" placeholder="Add a new task...">
<button id="add-todo">Add</button>
<ul id="todo-list"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
We set up the basic structure for our to-do list application in the HTML file. We included a title and linked the stylesheets needed for styling and icons. Inside the body tag, we created a container class that contains a heading, an input field for adding new tasks, an 'Add' button, and an empty list where the tasks will be displayed. And finally, for the logic of the to-do list application, we linked a JavaScript file.
JavaScript Functionality
In this JavaScript file, we will handle the functionality of our to-do list application. Include the following code in your script.js file.
document.addEventListener('DOMContentLoaded', () => {
// Get DOM elements
const addTodoButton = document.getElementById('add-todo');
const newTodoInput = document.getElementById('new-todo');
const todoList = document.getElementById('todo-list');
// Add event listener for adding a new todo
addTodoButton.addEventListener('click', () => {
const todoText = newTodoInput.value.trim();
if (todoText) {
const todoItem = createTodoItem(todoText);
todoList.appendChild(todoItem);
newTodoInput.value = '';
saveTodos();
}
});
// Load existing todos from local storage
loadTodos();
// Function to create a new todo item
function createTodoItem(text) {
const li = document.createElement('li');
li.innerHTML = `
<div class="item">
<input type="checkbox" class="complete-checkbox">
<div class="todo-text">${text}</div>
</div>
<button class="edit"><i class="fas fa-edit icon"></i></button>
<button class="delete"><i class="fas fa-trash icon"></i></button>`;
// Add event listeners for edit, complete, and delete
li.querySelector('.edit').addEventListener('click', editTodo);
li.querySelector('.complete-checkbox').addEventListener('change', completeTodo);
li.querySelector('.delete').addEventListener('click', deleteTodo);
return li;
}
// Function to edit a todo item
function editTodo() {
const li = this.parentElement;
const todoText = li.querySelector('.todo-text');
const newText = prompt('Edit your todo', todoText.textContent);
if (newText !== null) {
todoText.textContent = newText;
saveTodos();
}
}
// Function to mark a todo item as completed
function completeTodo() {
const li = this.parentElement;
li.classList.toggle('completed');
saveTodos();
}
// Function to delete a todo item
function deleteTodo() {
const li = this.parentElement;
if (confirm('Are you sure you want to delete this item?')) {
li.remove();
saveTodos();
}
}
// Function to save todos to local storage
function saveTodos() {
const todos = Array.from(todoList.children).map(li => ({
text: li.querySelector('.todo-text').textContent,
completed: li.classList.contains('completed')
}));
localStorage.setItem('todos', JSON.stringify(todos));
}
// Function to load todos from local storage
function loadTodos() {
const todos = JSON.parse(localStorage.getItem('todos')) || [];
todos.forEach(todo => {
const todoItem = createTodoItem(todo.text);
if (todo.completed) {
todoItem.classList.add('completed');
todoItem.querySelector('.complete-checkbox').checked = true;
}
todoList.appendChild(todoItem);
});
}
});
In this JavaScript code, we add the main features to our to-do list. When the page loads, we set up an event listener for the 'Add' button so users can add new tasks. Each task has an edit button to change the task text, a checkbox to mark it as complete, and a delete button to remove it. Tasks are saved in the browser's local storage, so they don't disappear when you close the browser. We use functions to create tasks, edit them, mark them as complete, delete them, and save/load tasks from local storage. This makes our to-do list easy to use and reliable.
Now that our project is finished, you can add tasks, mark them as complete, delete them, and they will be saved inside the local storage.
Styling with CSS
A good user experience starts with a well-designed interface, which we will achieve with CSS. Add the following code to your style.css file.
body {
font-family: Verdana, sans-serif;
background-color: rgb(176, 176, 176);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
overflow: hidden;
}
.container {
background: #1e1e1e;
padding: 20px;
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
border-radius: 10px;
border: 2px solid white;
width: 500px;
}
h1 {
text-align: center;
color: #ffffff;
font-size: 2rem;
margin-bottom: 20px;
}
input {
width: 100%;
padding: 10px;
margin: 5px 0 15px 0;
border: none;
border-radius: 5px;
background-color: #333;
color: #e0e0e0;
font-size: 1rem;
box-sizing: border-box;
}
input::placeholder {
color: #bbb;
}
#add-todo {
width: 100%;
padding: 10px;
background-color: #e3b736;
color: #ffffff;
border: none;
margin: 0 0 20px 0;
border-radius: 5px;
font-size: 1rem;
transition: 0.3s;
}
#add-todo:hover {
background-color: #d2aa31f5;
}
ul {
list-style-type: none;
max-height: 60vh;
padding: 0;
margin: 0;
padding-right: 10px;
overflow-y: auto;
display: flex;
flex-direction: column;
row-gap: 15px;
}
li {
background-color: #2c2c2c;
border-radius: 5px;
border: 1px solid #4d4d4d;
padding: 10px;
padding-top: 40px;
position: relative;
}
.item {
display: flex;
align-items: center;
gap: 10px;
}
.todo-text {
color: #e0e0e0;
flex-grow: 1;
}
.completed .todo-text {
text-decoration: line-through;
color: #e0e0e09e;
}
button {
border: none;
background-color: transparent;
cursor: pointer;
}
.edit {
position: absolute;
top: 5px;
right: 30px;
color: #2b9cd5;
}
.edit:hover {
color: #278fc2;
}
.delete {
position: absolute;
top: 5px;
right: 2px;
color: crimson;
}
.delete:hover {
color: rgb(203, 18, 55);
}
.icon {
font-size: 1rem;
}
.complete-checkbox {
height: 15px;
width: 15px;
}
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #1e1e1e;
}
::-webkit-scrollbar-thumb {
background: #333;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
Now, your user interface will resemble something like this.
We hope you have completed this project without any problems and also understood how all the functionality works.
Questions and answers
Here are some potential questions and their answers related to this project.
Q: How does local storage work in this to-do list application?
Ans: Local storage is utilized to store task data within the user's browser. Tasks are stored as JSON objects, which enables us to retrieve and display them persistently, even if the user refreshes the page or closes the browser. This is achieved by converting our JavaScript objects into JSON strings using JSON.stringify() before storing them in local storage. Later, when we need the tasks, we fetch the JSON strings from local storage and use JSON.parse() to turn them back into JavaScript objects.
Q: How does the 'Add Task' functionality work?
Ans: The 'Add Task' functionality allows users to input a new task into the to-do list. When the user enters text into the input field and clicks 'Add', the application creates a new list item dynamically. This item includes the task text and options for editing and deleting tasks. Tasks are stored locally using browser storage (localStorage), ensuring they remain saved even if the page is refreshed or closed.
Q: Describe the functionality behind the 'Edit' button for tasks.
Ans: The 'Edit' button allows users to modify existing tasks directly within the to-do list. When clicked, it prompts the user to edit the task text in a dialog box. Once edited, the task text updates in real-time within the task item.
Q: How is task completion managed in this application?
Ans: Task completion in this application is managed using checkboxes next to each task. When a user checks a checkbox, the corresponding task is visually marked as completed with a strikethrough style. This helps users keep track of their tasks easily.
Q: Explain the process for deleting a task from the list.
Ans: To delete a task from the list, users can click the 'Delete' button associated with the task they wish to remove. Upon clicking, a confirmation prompt appears asking if they are sure about deleting the task. If confirmed, the task is immediately removed from the list, simplifying task management by allowing users to easily eliminate tasks they no longer need.
Conclusion
Developing a to-do list app after learning HTML, CSS, and JavaScript will give you a lot of practice. Adding, editing, completing, and deleting tasks are core web development skills that are taught through the development of this project. Plus, you get to see how local storage works to save your actions even when you close the browser or refresh the page.
Learning important web development skills like DOM manipulation, event handling, and data management are possible through a to-do project. Every task you add, edit or delete is a real-world example of these concepts.
If you have any questions about this article or related to web development, you can ask them in the question box given below. You will get the answer soon.