DEV Community

Mohamud Dahir Abdi
Mohamud Dahir Abdi

Posted on • Edited on

To-Do List App Javascript

Complete To-Do List App with Dark Mode - Full Code Walkthrough

Here's the complete implementation of your modern To-Do List application with dark mode functionality, including all HTML, CSS, and JavaScript code.


In this step-by-step tutorial, i will create a feature-rich To-Do List app with:

✅ Dark/light mode toggle (auto-saves preference)

✅ Add, edit, delete, and mark tasks complete

✅ "Delete All" with confirmation

✅ Keyboard support (Enter key to add tasks)

✅ Persistent storage (tasks survive page refresh)

🔗 Full Code on GitHub


📱 App Preview (Live Demo)

Light Mode Dark Mode
Light Mode Dark Mode

📁 File Structure

📁 todo-app/ ├── 📄 index.html ├── 📄 style.css ├── 📄 script.js └── 📁 images/ ├── 📄 checked.png ├── 📄 delete.png ├── 📄 to-do-list-icon.png └── 📄 unchecked.png 
Enter fullscreen mode Exit fullscreen mode

🖥️ HTML (index.html)

<!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 App</title> <link rel="stylesheet" href="style.css" /> </head> <body> <!-- Dark Mode Toggle --> <div class="theme-toggle-container"> <button class="theme-toggle" id="theme-toggle"> <span class="toggle-icon">🌙</span> <span class="toggle-text">Dark Mode</span> </button> </div> <!-- To-Do List App --> <div class="container"> <div class="todo-app"> <h2> To-Do-List <span> <img src="images/to-do-list-icon.png" class="todo-icon" /> </span> </h2> <div class="row"> <input type="text" id="input-box" placeholder="Add your text" /> <button id="add-btn" onclick="addTask()" disabled>Add</button> </div> <ul id="list-container"></ul> <button id="delete-all" class="delete-all-btn">Delete All</button> </div> </div> <script src="script.js"></script> </body> </html> 
Enter fullscreen mode Exit fullscreen mode

🎨 CSS (style.css)

@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap"); :root { /* Light Mode Colors */ --primary-bg: linear-gradient( to right, #e3a1a1, #b0c4c4, #4fc2dd, #a897d6, #70c0d3 ); --app-bg: #ffffff; --text-color: #002655; --input-bg: #dfe2e5; --add-btn: #ff4d3a; --delete-all-btn: linear-gradient(to right, #ff5e6f, #b2e4ff, #ff5e6f); --list-item-bg: #ffffff; --checked-item: #666; /* Dark Mode Colors */ --dark-primary-bg: linear-gradient(to right, #101d26, #1c3544, #284c5e); --dark-app-bg: #1c1c1c; --dark-text-color: #f5f5f5; --dark-input-bg: #333; --dark-add-btn: #e65a5a; --dark-delete-all-btn: linear-gradient(to right, #ff3b5c, #ff4825); --dark-list-item-bg: #333; --dark-checked-item: #bbb; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: "Poppins", sans-serif; transition: background 0.3s, color 0.3s; } body { transition: background 0.5s ease, color 0.5s ease; } body.dark-mode { --primary-bg: var(--dark-primary-bg); --app-bg: var(--dark-app-bg); --text-color: var(--dark-text-color); --input-bg: var(--dark-input-bg); --add-btn: var(--dark-add-btn); --delete-all-btn: var(--dark-delete-all-btn); --list-item-bg: var(--dark-list-item-bg); --checked-item: var(--dark-checked-item); } .container { width: 100%; min-height: 100vh; background: var(--primary-bg); padding: 10px; } .todo-app { width: 100%; max-width: 540px; background: var(--app-bg); margin: 100px auto 20px; padding: 40px 30px 70px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); } .todo-app h2 { color: var(--text-color); display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; } .todo-app h2 img.todo-icon { width: 60px; height: 60px; margin-left: 10px; } .row { display: flex; align-items: center; justify-content: space-between; background: var(--input-bg); border-radius: 30px; padding-left: 20px; margin-bottom: 25px; } input { flex: 1; outline: none; border: none; background: transparent; padding: 10px; font-size: 14px; color: var(--text-color); } button { border: none; outline: none; padding: 16px 50px; background: var(--add-btn); color: #fff; font-size: 16px; cursor: pointer; border-radius: 40px; font-weight: 500; } /* Disable button style */ button:disabled { background: gray; cursor: not-allowed; } /* To-Do List Items */ ul li { list-style: none; font-size: 17px; padding: 12px 8px 12px 50px; user-select: none; cursor: pointer; position: relative; background: var(--list-item-bg); margin-bottom: 8px; color: var(--text-color); border-radius: 8px; } /* Checkbox icon before list items */ ul li::before { content: ""; position: absolute; height: 28px; width: 28px; border-radius: 50%; background-image: url(images/unchecked.png); background-size: cover; background-position: center; top: 12px; left: 8px; } /* Checked list item */ ul li.checked { color: var(--checked-item); text-decoration: line-through; } /* Change checkbox image when checked */ ul li.checked::before { background-image: url(images/checked.png); } /* Delete icon */ ul li .delete-icon { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; cursor: pointer; opacity: 0.7; transition: opacity 0.2s; filter: var(--icon-filter); } ul li .delete-icon:hover { opacity: 1; } /* Delete All Button */ .delete-all-btn { background: var(--delete-all-btn); margin: 20px auto 0; padding: 15px 45px; text-align: center; transition: 0.5s; background-size: 200% auto; color: white; border-radius: 10px; display: block; border: none; font-weight: 500; cursor: pointer; } .delete-all-btn:hover { background-position: right center; } /* Dark Mode Specific */ body.dark-mode .delete-icon { filter: invert(1); } body.dark-mode ul li { box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } /* Theme Toggle Button - Top Left */ .theme-toggle-container { position: absolute; top: 20px; left: 20px; } .theme-toggle { background: linear-gradient(to right, #6a11cb 0%, #2575fc 100%); color: white; border: none; padding: 12px 25px; border-radius: 30px; cursor: pointer; font-size: 16px; font-weight: 500; transition: all 0.3s ease; } .theme-toggle:hover { transform: translateY(-2px); } body.dark-mode .theme-toggle { background: linear-gradient(to right, #f5af19 0%, #f12711 100%); color: #fff; } 
Enter fullscreen mode Exit fullscreen mode

⚡ JavaScript (script.js)

const inputBox = document.getElementById("input-box"); const listContainer = document.getElementById("list-container"); const deleteAllBtn = document.getElementById("delete-all"); const themeToggle = document.getElementById("theme-toggle"); const toggleIcon = themeToggle.querySelector(".toggle-icon"); const toggleText = themeToggle.querySelector(".toggle-text"); const addButton = document.getElementById("add-btn"); // Initialize theme function initTheme() { const isDark = localStorage.getItem("darkMode") === "true"; if (isDark) document.body.classList.add("dark-mode"); updateThemeButton(isDark); } // Update theme button function updateThemeButton(isDark) { toggleIcon.textContent = isDark ? "☀️" : "🌙"; toggleText.textContent = isDark ? "Light Mode" : "Dark Mode"; } // Toggle theme themeToggle.addEventListener("click", () => { const isDark = document.body.classList.toggle("dark-mode"); localStorage.setItem("darkMode", isDark); updateThemeButton(isDark); }); // Disable Add button when input is empty inputBox.addEventListener("input", () => { addButton.disabled = inputBox.value.trim() === ""; }); // Add new task function addTask() { if (inputBox.value.trim() === "") { alert("Please enter a task"); return; } const li = document.createElement("li"); li.textContent = inputBox.value.trim(); const deleteIcon = document.createElement("img"); deleteIcon.src = "images/delete.png"; deleteIcon.className = "delete-icon"; deleteIcon.alt = "Delete task"; li.appendChild(deleteIcon); listContainer.appendChild(li); inputBox.value = ""; addButton.disabled = true; // Disable button after adding task saveData(); updateDeleteAllVisibility(); } // Handle list interactions (check/uncheck and delete) listContainer.addEventListener("click", function (e) { if (e.target.tagName === "LI") { e.target.classList.toggle("checked"); saveData(); } else if (e.target.classList.contains("delete-icon")) { e.target.parentElement.remove(); saveData(); updateDeleteAllVisibility(); } }); // Delete all tasks deleteAllBtn.addEventListener("click", function () { if (listContainer.children.length === 0) return; if (confirm("Are you sure you want to delete ALL tasks?")) { listContainer.innerHTML = ""; saveData(); updateDeleteAllVisibility(); } }); // Save data to localStorage function saveData() { localStorage.setItem("data", listContainer.innerHTML); } // Load tasks from localStorage function showTask() { listContainer.innerHTML = localStorage.getItem("data") || ""; updateDeleteAllVisibility(); } // Show/hide Delete All button based on tasks function updateDeleteAllVisibility() { deleteAllBtn.style.display = listContainer.children.length > 0 ? "block" : "none"; } // Initialize app initTheme(); showTask(); // Add task on Enter key press inputBox.addEventListener("keypress", function (e) { if (e.key === "Enter") { addTask(); } }); 
Enter fullscreen mode Exit fullscreen mode

🌟 Key Features Explained

  1. Dark/Light Mode Toggle

    • Uses CSS variables for easy theme switching
    • Saves user preference in localStorage
  2. Task Management

    • Add tasks by clicking "Add" or pressing Enter
    • Mark tasks as complete by clicking them
    • Delete individual tasks with the trash icon
    • "Delete All" button with confirmation
  3. Data Persistence

    • All tasks are saved to localStorage automatically
    • Tasks persist even after closing/reopening the browser
  4. User Experience

    • "Add" button disabled when input is empty
    • Smooth transitions between themes
    • Responsive design works on all devices

🚀 How to Use This App

  1. Download all files and images
  2. Open index.html in your browser
  3. Start adding tasks!
  4. Toggle between light/dark mode using the button

You can find the complete project on GitHub:

🔗 GitHub Repository

Top comments (0)