Hey there, fellow coder! If you’re like me, you probably love building things that are both practical and fun. A To-Do app is the perfect project to do just that.
It’s not only a great way to practice your HTML, CSS, and JavaScript skills, but you also end up with a tool that you can actually use to stay organized! (And who doesn’t need help with that, right?)
I’ve built quite a few versions of to-do apps over the years, and they always get me excited because they’re a great way to get your hands dirty with basic JavaScript concepts like events, DOM manipulation, and local storage.
So, let’s dive into building a simple, yet functional, To-Do app that’ll let you add, delete, and mark tasks as completed.
Step 1: Setting Up the Structure (HTML)
First things first, let’s lay the foundation with some basic HTML. We’ll need an input field to add tasks, a button to submit them, and an area to display our to-do items.
Here’s the HTML structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To-Do App</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="app-container">
<h1>My To-Do List</h1>
<input type="text" id="task-input" placeholder="Enter your task here...">
<button id="add-task-btn">Add Task</button>
<ul id="task-list"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
Explanation:
- The
input
field allows you to type in tasks. - The
button
adds the task to the list. - The
ul
(unordered list) will display the tasks.
Personal anecdote: When I first started working on projects like this, I kept things super simple. It was just an input box, a button, and some basic JavaScript to add the tasks.
The key was getting it working first, then refining the UI and features later. You’ll be surprised how much you learn along the way!
Step 2: Styling the App (CSS)
Now that we have the structure in place, let’s style it a little. You don’t need anything fancy—just something clean and easy to use. But trust me, taking a little time to make your app look nice can make a world of difference.
Here’s a basic CSS file to start (style.css
):
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.app-container {
width: 300px;
margin: 50px auto;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
text-align: center;
}
h1 {
color: #333;
margin-bottom: 20px;
}
#task-input {
width: 70%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
#add-task-btn {
padding: 10px 20px;
margin-left: 10px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
#task-list {
list-style: none;
padding: 0;
margin-top: 20px;
}
#task-list li {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #f9f9f9;
padding: 10px;
margin-bottom: 10px;
border-radius: 4px;
}
#task-list li.completed {
text-decoration: line-through;
color: #ccc;
}
Explanation:
- I’ve given the app a simple container with some padding and a shadow to make it pop.
- The tasks will display in a nice list format with some spacing and borders.
- I also added a style for when a task is marked as “completed” (we’ll get to that in a minute).
Personal anecdote: Styling was always my favorite part when I first started web development. I loved the instant gratification of seeing my changes reflected in real time.
I remember adding my first CSS class to style my To-Do app and feeling like a wizard!
Step 3: Making It Interactive with JavaScript
Here comes the fun part—making your app actually work with JavaScript. We’ll handle three main actions: adding tasks, deleting tasks, and marking them as completed.
Here’s the JavaScript to get things working (script.js
):
const addTaskButton = document.getElementById('add-task-btn');
const taskInput = document.getElementById('task-input');
const taskList = document.getElementById('task-list');
// Function to add a task
function addTask() {
const taskText = taskInput.value.trim();
if (taskText === '') return; // Don't add empty tasks
const taskItem = document.createElement('li');
taskItem.textContent = taskText;
// Add a delete button to each task
const deleteButton = document.createElement('button');
deleteButton.textContent = 'Delete';
deleteButton.onclick = () => taskItem.remove();
taskItem.appendChild(deleteButton);
// Toggle task completion
taskItem.onclick = () => taskItem.classList.toggle('completed');
// Add the task to the list
taskList.appendChild(taskItem);
// Clear the input field
taskInput.value = '';
}
// Event listener for the "Add Task" button
addTaskButton.addEventListener('click', addTask);
// Optional: Allow pressing "Enter" to add task
taskInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
addTask();
}
});
Explanation:
- Adding a Task: When you click the “Add Task” button, we grab the text from the input field, create a new list item (
li
), and add it to the list. - Delete Button: Each task gets a “Delete” button, which removes the task when clicked.
- Marking as Completed: Clicking on a task toggles the
completed
class, which adds the strikethrough effect (via CSS). - Enter Key: If you press “Enter,” the task is added, just like clicking the button. It’s all about making things feel smooth!
Personal anecdote: I remember the first time I saw my To-Do app in action—how satisfying it was to click through tasks, mark them as completed, and remove them from the list.
It felt like a simple yet powerful tool, and that’s the beauty of this app: it’s not too complex, but it teaches you a lot about interactivity!
Step 4: Adding Persistence with Local Storage (Optional)
If you want your tasks to persist even after a page refresh (so they’re not lost when you accidentally close the tab), we can use localStorage. This part is a bit more advanced, but it’s totally worth adding!
Here’s how to modify the code to save tasks to local storage:
// Function to load tasks from localStorage
function loadTasks() {
const tasks = JSON.parse(localStorage.getItem('tasks')) || [];
tasks.forEach(task => {
const taskItem = document.createElement('li');
taskItem.textContent = task.text;
if (task.completed) taskItem.classList.add('completed');
const deleteButton = document.createElement('button');
deleteButton.textContent = 'Delete';
deleteButton.onclick = () => {
taskItem.remove();
saveTasks();
};
taskItem.appendChild(deleteButton);
taskItem.onclick = () => {
taskItem.classList.toggle('completed');
saveTasks();
};
taskList.appendChild(taskItem);
});
}
// Function to save tasks to localStorage
function saveTasks() {
const tasks = [];
document.querySelectorAll('#task-list li').forEach(taskItem => {
tasks.push({
text: taskItem.textContent.replace('Delete', '').trim(),
completed: taskItem.classList.contains('completed')
});
});
localStorage.setItem('tasks', JSON.stringify(tasks));
}
// Load tasks on page load
loadTasks();
// Add task and save on add
addTaskButton.addEventListener('click', () => {
addTask();
saveTasks();
});
Explanation:
loadTasks()
loads tasks from localStorage when the page is refreshed.saveTasks()
saves the tasks back to localStorage whenever the list is updated.- The tasks will persist even after a refresh, so your to-do list will be there whenever you return.
And that’s it! You’ve just created a basic To-Do app using HTML, CSS, and JavaScript. It may seem simple at first, but you’ve learned some key concepts: DOM manipulation, events, localStorage, and of course, the satisfaction of seeing your code come to life.
If you’re like me, you’ll find yourself using this app to organize your day, and over time, you can add even more features like task due dates, categories, or even a priority system.
I hope you had as much fun building this as I did! Keep experimenting, and remember—coding is all about learning by doing. If you run into any challenges, just keep going; you’ll get there. Happy coding!
Discover more from Prime Inspire
Subscribe to get the latest posts sent to your email.