🚀 Build a Simple To-Do List App with Vanilla JavaScript (No Frameworks Needed!)

build-todo-list-app-with-vanilla-javascript


🧠 Introduction

Looking to build your first real JavaScript project? A To-Do List App is the perfect place to start. It’s small, manageable, and teaches you key skills like DOM manipulationevent handling, and data persistence.

By the end of this beginner-friendly tutorial, you'll have built a working task tracker — right in your browser — with HTMLCSS, and vanilla JavaScript. No frameworks, no fluff. Just hands-on learning.

Let’s start building — snippet by snippet!


🧱 Step 1: Set Up Your HTML Structure

First, we’ll create the basic layout for our to-do app: an input box, a button to add tasks, and an empty list to display them.

🔹 HTML Snippet

<div class="todo-container">
  <h1>My To-Do List</h1>
  <input type="text" id="todo-input" placeholder="Enter a task..." />
  <button id="add-btn">Add</button>
  <ul id="todo-list"></ul>
</div>

✅ Explanation

  • We wrap everything inside a .todo-container for styling purposes.
  • The input field lets users type in tasks.
  • The button triggers adding tasks to the list.
  • The ul (unordered list) will hold each task as a list item.

🎨 Step 2: Style the App with CSS

Let’s make it a bit more appealing with some basic CSS.

🔹 CSS Snippet

body {
  margin: 0;
  padding: 0;
  background: linear-gradient(to right, #667eea, #764ba2);
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

.todo-container {
  background-color: #fff;
  border-radius: 12px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
  padding: 30px;
  max-width: 400px;
  width: 90%;
  text-align: center;
}

.todo-container h1 {
  margin-bottom: 20px;
  color: #333;
}

#todo-input {
  width: 70%;
  padding: 10px 12px;
  border: 1px solid #ccc;
  border-radius: 6px;
  font-size: 16px;
  outline: none;
  transition: border 0.3s ease;
}

#todo-input:focus {
  border-color: #667eea;
}

#add-btn {
  padding: 10px 16px;
  margin-left: 10px;
  background-color: #667eea;
  border: none;
  border-radius: 6px;
  color: white;
  font-weight: bold;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

#add-btn:hover {
  background-color: #556cd6;
}

#todo-list {
  list-style: none;
  padding: 0;
  margin-top: 25px;
}

#todo-list li {
  background-color: #f5f5f5;
  padding: 12px 16px;
  margin-bottom: 12px;
  border-radius: 6px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: background-color 0.2s ease;
}

#todo-list li:hover {
  background-color: #e0e0e0;
}

#todo-list button {
  background-color: transparent;
  border: none;
  font-size: 18px;
  cursor: pointer;
  color: #ff5c5c;
  transition: color 0.3s ease;
}

#todo-list button:hover {
  color: #e60000;
}

✅ Explanation

  • We center the app and set a clean font.
  • Input and button spacing improves usability.
  • The list is styled to remove bullet points and spacing.

🧠 Step 3: Add JavaScript to Handle Task Addition

Now let’s wire up the input and button to actually add tasks to the list.

🔹 JavaScript Snippet (Part 1)

const input = document.getElementById("todo-input");
const addBtn = document.getElementById("add-btn");
const list = document.getElementById("todo-list");

addBtn.addEventListener("click", () => {
  const task = input.value.trim();
  if (task) {
    const li = document.createElement("li");
    li.textContent = task;
    list.appendChild(li);
    input.value = "";
  }
});

✅ Explanation

  • We fetch references to the input, button, and list.
  • On button click, we:
    • Grab the input value
    • Check if it's not empty
    • Create a new li element
    • Add the task to the list
    • Clear the input field

🗑️ Step 4: Add Delete Functionality

What good is a to-do list if you can’t remove tasks?

🔹 JavaScript Snippet (Part 2)

Update the addEventListener function:

addBtn.addEventListener("click", () => {
  const task = input.value.trim();
  if (task) {
    const li = document.createElement("li");
    li.textContent = task;

    const deleteBtn = document.createElement("button");
    deleteBtn.textContent = "❌";
    deleteBtn.style.marginLeft = "10px";
    deleteBtn.addEventListener("click", () => {
      li.remove();
    });

    li.appendChild(deleteBtn);
    list.appendChild(li);
    input.value = "";
  }
});

✅ Explanation

  • We create a "delete" button (❌ emoji style).
  • When clicked, it removes the parent li from the DOM.
  • This keeps your task list clean and under control.

💾 Step 5: Save Tasks with LocalStorage

Want your to-dos to stick around even after refreshing? Let’s use localStorage.

🔹 JavaScript Snippet (Part 3)

First, update your functions:

function saveTasks() {
  const tasks = [];
  list.querySelectorAll("li").forEach(li => {
    const taskText = li.firstChild.textContent;
    tasks.push(taskText);
  });
  localStorage.setItem("tasks", JSON.stringify(tasks));
}

Then, call saveTasks() whenever tasks change:

deleteBtn.addEventListener("click", () => {
  li.remove();
  saveTasks();
});

addBtn.addEventListener("click", () => {
  // ... rest of code
  list.appendChild(li);
  input.value = "";
  saveTasks();
});

✅ Explanation

  • saveTasks() grabs all task texts and stores them as a JSON string.
  • We call this function every time we add or remove a task.

🔁 Step 6: Load Tasks on Page Load

Finally, load saved tasks when the page loads.

🔹 JavaScript Snippet (Part 4)

function loadTasks() {
  const tasks = JSON.parse(localStorage.getItem("tasks")) || [];
  tasks.forEach(task => {
    const li = document.createElement("li");
    li.textContent = task;

    const deleteBtn = document.createElement("button");
    deleteBtn.textContent = "❌";
    deleteBtn.style.marginLeft = "10px";
    deleteBtn.addEventListener("click", () => {
      li.remove();
      saveTasks();
    });

    li.appendChild(deleteBtn);
    list.appendChild(li);
  });
}

window.addEventListener("DOMContentLoaded", loadTasks);

✅ Explanation

  • On DOMContentLoaded, we load saved tasks.
  • Each is rendered just like when we add them manually.

🔧 Gentle Reminder

Once you're done following the steps above, go ahead and combine all the snippets into your HTML, CSS, and JS files. You’ll see your fully working to-do list app right in the browser. 🎉


✅ Best Practices & Tips

  • Use class names instead of inline styles for larger projects.
  • Consider accessibility (e.g., adding aria-labels or semantic HTML).
  • Add task validation (e.g., prevent duplicate entries).
  • Use keyboard shortcuts (e.g., add task on "Enter" key press).

🔍 SEO & Performance Tie-In

A fast-loading, minimal JavaScript app like this can improve site speed and user engagement, which are key factors in SEO rankings. Clean, interactive features also reduce bounce rate and increase time-on-page.


📌 Conclusion

You just built a fully functional to-do list app using pure JavaScript — and picked up critical skills in DOM manipulation, event handling, and local storage.

💬 Got questions or ideas? Leave a comment below. 🚀 Want more? Check out our other tutorials on JavaScript basicsproject building, and web automation!

Post a Comment

0 Comments