Practice: Building an Interactive To-Do List with DOM
Creating a to-do list is one of those beginner-friendly JavaScript projects that teaches you how to work with the DOM in a real, useful way. You’ll create elements with JavaScript, add them to the page, respond to user actions like clicks, and remove elements dynamically. It’s a perfect hands-on way to understand how everything connects.
Add tasks
To start, we need a way for the user to type a task and add it to the list.
What we need:
- An input box for entering tasks.
- A button to add the task.
- A place to show the list (a
<ul>
element).
Here’s how we’ll do it in JavaScript:
const taskInput = document.getElementById("taskInput");
const addTaskBtn = document.getElementById("addTaskBtn");
const taskList = document.getElementById("taskList");
We grab the input field, the button, and the task list from the DOM using getElementById
.
Then we listen for a click on the "Add" button:
addTaskBtn.addEventListener("click", () => {
const taskText = taskInput.value.trim();
if (taskText === "") return;
});
We get the text from the input, remove extra spaces, and ignore empty entries.
Now we create a new task item:
const li = document.createElement("li");
const taskSpan = document.createElement("span");
taskSpan.textContent = taskText;
li
is the list item.taskSpan
holds the text.
We attach them like this:
li.appendChild(taskSpan);
taskList.appendChild(li);
Now the task shows up in the list when the button is clicked.
Mark tasks as completed
We want users to click on a task to mark it done. We do this by toggling a class when the text is clicked:
taskSpan.addEventListener("click", () => {
li.classList.toggle("completed");
});
In our CSS, this .completed
class applies a line-through style. Simple, clear feedback.
Delete tasks
We also need a way to remove tasks. Each task will get a small "Delete" button.
Here’s the code:
const deleteBtn = document.createElement("button");
deleteBtn.textContent = "Delete";
deleteBtn.className = "delete-btn";
deleteBtn.addEventListener("click", () => {
li.remove();
});
This creates a button, gives it some text and a class, and removes the entire li
when clicked.
Then we attach the delete button:
li.appendChild(deleteBtn);
Clear the input
After adding a task, we want to reset the input so the user can type a new one:
taskInput.value = "";
taskInput.focus();
Final Code (HTML, CSS, JavaScript)
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Learn DOM manipulation by building a simple interactive to-do list with HTML, CSS, and JavaScript." />
<title>To-Do List Practice</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<h1>My To-Do List</h1>
<div class="input-group">
<input type="text" id="taskInput" placeholder="Add a new task..." />
<button id="addTaskBtn">Add</button>
</div>
<ul id="taskList"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
CSS (style.css)
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
background: #f4f4f4;
padding: 40px;
display: flex;
justify-content: center;
}
.container {
background: white;
padding: 20px 30px;
border-radius: 8px;
width: 100%;
max-width: 400px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
margin-bottom: 20px;
}
.input-group {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
#taskInput {
flex: 1;
padding: 10px;
font-size: 16px;
}
#addTaskBtn {
padding: 10px 16px;
font-size: 16px;
background: #007bff;
color: white;
border: none;
cursor: pointer;
border-radius: 4px;
}
#addTaskBtn:hover {
background: #0056b3;
}
#taskList {
list-style: none;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
background: #f9f9f9;
padding: 10px;
margin-bottom: 8px;
border-radius: 4px;
transition: background 0.2s;
}
li.completed span {
text-decoration: line-through;
color: #888;
}
.delete-btn {
background: transparent;
border: none;
color: #dc3545;
font-weight: bold;
cursor: pointer;
}
JavaScript (script.js)
const taskInput = document.getElementById("taskInput");
const addTaskBtn = document.getElementById("addTaskBtn");
const taskList = document.getElementById("taskList");
addTaskBtn.addEventListener("click", () => {
const taskText = taskInput.value.trim();
if (taskText === "") return;
const li = document.createElement("li");
const taskSpan = document.createElement("span");
taskSpan.textContent = taskText;
taskSpan.addEventListener("click", () => {
li.classList.toggle("completed");
});
const deleteBtn = document.createElement("button");
deleteBtn.textContent = "Delete";
deleteBtn.className = "delete-btn";
deleteBtn.addEventListener("click", () => {
li.remove();
});
li.appendChild(taskSpan);
li.appendChild(deleteBtn);
taskList.appendChild(li);
taskInput.value = "";
taskInput.focus();
});