Photo by David Schultz on Unsplash
To-Do List Design Using HTML, CSS, and JavaScript
Create a modern, responsive to-do list using HTML, CSS, and JavaScript, featuring task input, completion toggles, deletion, and local storage for persistence. This implementation focuses on clean design, accessible interactions, and maintainable code structure, ideal for task management.
Prerequisites
- Basic HTML, CSS, and JavaScript knowledge
- A code editor (e.g., VS Code)
Part 1: To-Do List Design
Step 1: HTML Structure (index.html)
Create a semantic HTML structure for the to-do list with an input form and a list for tasks.
<div class="todo-container" role="region" aria-label="To-Do List">
<div class="todo-header">
<input type="text" class="todo-input" placeholder="Add a new task..." aria-label="New task input">
<button class="todo-add-btn">Add</button>
</div>
<ul class="todo-list" id="todoList"></ul>
</div>
Step 2: Core CSS Implementation (styles.css)
Style the to-do list with a clean layout, interactive states, and responsive design.
:root {
--gray-900: #111827;
--gray-700: #374151;
--gray-200: #e5e7eb;
--gray-100: #f3f4f6;
--white: #ffffff;
--primary-600: #2563eb;
--primary-500: #3b82f6;
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 12px;
--spacing-lg: 16px;
--radius-sm: 4px;
--radius-md: 6px;
--transition: 0.2s ease;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.todo-container {
max-width: 500px;
width: 100%;
background: var(--white);
border-radius: var(--radius-md);
box-shadow: var(--shadow-md);
padding: var(--spacing-lg);
}
.todo-header {
display: flex;
gap: var(--spacing-sm);
margin-bottom: var(--spacing-md);
}
.todo-input {
flex: 1;
padding: var(--spacing-sm);
font-size: 0.9375rem;
border: 1px solid var(--gray-200);
border-radius: var(--radius-sm);
transition: border-color var(--transition);
}
.todo-input:focus {
outline: none;
border-color: var(--primary-500);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
.todo-add-btn {
padding: var(--spacing-sm) var(--spacing-md);
background: var(--primary-500);
color: var(--white);
border: none;
border-radius: var(--radius-sm);
font-size: 0.9375rem;
font-weight: 500;
cursor: pointer;
transition: background var(--transition);
}
.todo-add-btn:hover {
background: var(--primary-600);
}
.todo-add-btn:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
.todo-list {
list-style: none;
padding: 0;
margin: 0;
}
.todo-item {
display: flex;
align-items: center;
gap: var(--spacing-sm);
padding: var(--spacing-sm) 0;
border-bottom: 1px solid var(--gray-200);
}
.todo-item:last-child {
border-bottom: none;
}
.todo-checkbox {
width: 18px;
height: 18px;
cursor: pointer;
}
.todo-text {
flex: 1;
font-size: 0.937,5rem;
color: var(--gray-900);
}
.todo-text.completed {
text-decoration: line-through;
color: var(--gray-700);
}
.todo-delete-btn {
background: none;
border: none;
color: var(--gray-700);
font-size: 1rem;
cursor: pointer;
padding: var(--spacing-xs);
transition: color var(--transition);
}
.todo-delete-btn:hover {
color: var(--gray-900);
}
.todo-delete-btn:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
@media (max-width: 640px) {
.todo-container {
width: 95%;
}
.todo-input {
font-size: 0.875rem;
}
.todo-add-btn {
padding: var(--spacing-xs) var(--spacing-sm);
font-size: 0.875rem;
}
.todo-text {
font-size: 0.875rem;
}
}
Step 3: JavaScript Implementation (script.js)
Add JavaScript to handle adding, completing, and deleting tasks, with local storage for persistence.
document.addEventListener('DOMContentLoaded', () => {
const todoInput = document.querySelector('.todo-input');
const todoAddBtn = document.querySelector('.todo-add-btn');
const todoList = document.querySelector('.todo-list');
// Load tasks from local storage
const tasks = JSON.parse(localStorage.getItem('tasks')) || [];
// Render tasks
const renderTasks = () => {
todoList.innerHTML = '';
tasks.forEach((task, index) => {
const li = document.createElement('li');
li.className = 'todo-item';
li.innerHTML = `
${task.text}
`;
todoList.appendChild(li);
// Handle checkbox toggle
const checkbox = li.querySelector('.todo-checkbox');
checkbox.addEventListener('change', () => {
tasks[index].completed = checkbox.checked;
saveTasks();
renderTasks();
});
// Handle delete
const deleteBtn = li.querySelector('.todo-delete-btn');
deleteBtn.addEventListener('click', () => {
tasks.splice(index, 1);
saveTasks();
renderTasks();
});
});
};
// Save tasks to local storage
const saveTasks = () => {
localStorage.setItem('tasks', JSON.stringify(tasks));
};
// Add new task
todoAddBtn.addEventListener('click', () => {
const text = todoInput.value.trim();
if (text) {
tasks.push({ text, completed: false });
saveTasks();
renderTasks();
todoInput.value = '';
todoInput.focus();
}
});
// Add task on Enter key
todoInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
todoAddBtn.click();
}
});
// Initial render
renderTasks();
});
Explanation
- Layout: A container holds a header with an input and add button, and a list for tasks. Each task includes a checkbox, text, and delete button.
- Interactivity: JavaScript enables adding tasks via button or Enter key, toggling completion with checkboxes, and deleting tasks. Tasks persist in local storage.
- Styling: Tasks are styled with flexbox for alignment, borders for separation, and hover/focus effects. Completed tasks have a strikethrough.
- Visual Feedback: The add button darkens on hover (
--primary-600); focus states use a blue ring; delete buttons darken on hover. - Responsiveness: A media query (
@media (max-width: 640px)) adjusts widths and font sizes for mobile usability. - Accessibility:
role="region",aria-labelon inputs and buttons, and focus management ensure screen reader compatibility. Keyboard support includes Enter key for adding tasks.
Accessibility Features
- Use
role="region"andaria-labelfor semantic structure - Ensure high contrast ratios for text and buttons (4.5:1 minimum)
- Support keyboard navigation with focus states and Enter key
- Provide descriptive
aria-labelfor interactive elements
Golden Rules
- Use CSS variables for consistent theming
- Implement focus states and ARIA for accessibility
- Provide clear visual feedback for interactions
- Optimize for mobile with responsive design
Conclusion
A professional to-do list should maintain visual clarity, provide intuitive interactions, remain responsive, and follow accessibility guidelines. This solution uses HTML, CSS, and JavaScript for a polished task manager with persistent storage. Experiment with features like task categories, due dates, or styling to match your design. Test across devices and browsers for usability. Feel free to leave comments with any questions or suggestions!
Comments
Post a Comment