Kanban Board (Drag & Drop) with HTML, CSS & JavaScript
40 DAYS 40 PROJECT CHALLENGE
Day #02
Project Overview
A modern Kanban Board built using HTML, CSS, and JavaScript, designed with a clean and responsive interface for managing tasks efficiently.
The board allows users to create, edit, delete, and move tasks between different workflow stages such as To Do, In Progress, and Done using drag-and-drop functionality. It demonstrates frontend concepts such as DOM manipulation, drag-and-drop interactions, modal forms, dark mode toggle, and LocalStorage-based task management, making it an ideal project for beginners learning real-world task management UI development.
Key Features
- Task management system with options to create, update, and remove tasks
- Move tasks across different stages using drag and drop functionality
- Fully responsive Kanban layout that works on desktop, tablet, and mobile
- Priority tags to categorize tasks as low, medium, or high
- Option to set due dates for better task organization
- Popup modal form for adding and editing tasks easily
- Dark mode switch for a comfortable viewing experience
- Browser LocalStorage used to save and retain tasks
- Simple and clean interface for clear task management
- Dynamic interactions handled using JavaScript DOM manipulation
HTML Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Kanban Board</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Kanban Board</h1>
<button id="themeToggle">🌙</button>
</header>
<main class="board">
<div class="column" data-status="todo">
<div class="column-header">
<h2>To Do</h2>
<button onclick="openModal('todo')">+</button>
</div>
<div class="task-list"></div>
</div>
<div class="column" data-status="progress">
<div class="column-header">
<h2>In Progress</h2>
<button onclick="openModal('progress')">+</button>
</div>
<div class="task-list"></div>
</div>
<div class="column" data-status="done">
<div class="column-header">
<h2>Done</h2>
<button onclick="openModal('done')">+</button>
</div>
<div class="task-list"></div>
</div>
</main>
<!-- Modal -->
<div class="modal" id="modal">
<div class="modal-box">
<h3>Add Task</h3>
<input type="text" id="taskTitle" placeholder="Task title">
<input type="date" id="taskDate">
<select id="taskPriority">
<option value="low">Low Priority</option>
<option value="medium">Medium Priority</option>
<option value="high">High Priority</option>
</select>
<div class="modal-actions">
<button onclick="saveTask()">Save</button>
<button onclick="closeModal()">Cancel</button>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html> CSS Code
:root{
--bg:#042354;
--card:#ffffff;
--text:#222;
--border:#e5e7eb;
}
body.dark{
--bg:#042354;
--card:#1f2937;
--text:#f3f4f6;
--border:#374151;
}
*{
margin:0;
padding:0;
box-sizing:border-box;
font-family:system-ui;
}
body{
background:var(--bg);
color:var(--text);
}
header{
display:flex;
justify-content:space-between;
align-items:center;
padding:20px;
}
header button{
border:1px solid var(--border);
background:var(--card);
padding:6px 12px;
border-radius:6px;
cursor:pointer;
}
.board{
display:flex;
gap:20px;
padding:20px;
flex-wrap:wrap;
}
.column{
background:var(--card);
border:1px solid var(--border);
border-radius:10px;
padding:15px;
flex:1;
min-width:280px;
}
.column-header{
display:flex;
justify-content:space-between;
align-items:center;
margin-bottom:15px;
}
.column-header button{
background:#6366f1;
color:white;
border:none;
width:28px;
height:28px;
border-radius:6px;
cursor:pointer;
}
.task-list{
min-height:150px;
}
.task{
background:var(--bg);
border:1px solid var(--border);
padding:10px;
border-radius:8px;
margin-bottom:10px;
cursor:grab;
}
.task strong{
font-size:14px;
color: #ffffff;
}
.task small{
display:block;
font-size:12px;
opacity:0.7;
margin-top:4px;
color: #ffffff;
}
.priority{
display:inline-block;
font-size:11px;
padding:2px 6px;
border-radius:4px;
margin-top:6px;
}
.low{
background:#d1fae5;
color:#065f46;
}
.medium{
background:#fef3c7;
color:#92400e;
}
.high{
background:#fee2e2;
color:#991b1b;
}
.task-actions{
display:flex;
gap:8px;
margin-top:8px;
}
.task-actions button{
border:none;
padding:4px 6px;
font-size:11px;
border-radius:4px;
cursor:pointer;
}
.edit-btn{
background:#6366f1;
color:white;
}
.delete-btn{
background:#ef4444;
color:white;
}
.modal{
display:none;
position:fixed;
inset:0;
background:rgba(0,0,0,0.4);
justify-content:center;
align-items:center;
}
.modal-box{
background:var(--card);
padding:20px;
border-radius:10px;
width:300px;
}
.modal-box input,
.modal-box select{
width:100%;
padding:8px;
margin-bottom:10px;
border:1px solid var(--border);
border-radius:6px;
}
.modal-actions{
display:flex;
justify-content:space-between;
}
.modal-actions button{
background:#6366f1;
color:white;
border:none;
padding:6px 12px;
border-radius:6px;
cursor:pointer;
}
@media(max-width:768px){
.board{
flex-direction:column;
}
} Javascript Code
let tasks = JSON.parse(localStorage.getItem("tasks")) || [];
let currentStatus = "";
let editId = null;
function saveStorage(){
localStorage.setItem("tasks",JSON.stringify(tasks));
}
function renderTasks(){
document.querySelectorAll(".task-list").forEach(list=>list.innerHTML="");
tasks.forEach(task=>{
const div=document.createElement("div");
div.className="task";
div.draggable=true;
div.dataset.id=task.id;
div.innerHTML=`
<strong>${task.title}</strong>
<small>Due: ${task.date || "No date"}</small>
<span class="priority ${task.priority}">${task.priority}</span>
<div class="task-actions">
<button class="edit-btn" onclick="editTask(${task.id})">Edit</button>
<button class="delete-btn" onclick="deleteTask(${task.id})">Delete</button>
</div>
`;
div.addEventListener("dragstart",e=>{
e.dataTransfer.setData("text",task.id);
});
document
.querySelector(`[data-status="${task.status}"] .task-list`)
.appendChild(div);
});
saveStorage();
}
function openModal(status){
currentStatus=status;
document.getElementById("modal").style.display="flex";
}
function closeModal(){
document.getElementById("modal").style.display="none";
document.getElementById("taskTitle").value="";
document.getElementById("taskDate").value="";
editId=null;
}
function saveTask(){
const title=document.getElementById("taskTitle").value;
const date=document.getElementById("taskDate").value;
const priority=document.getElementById("taskPriority").value;
if(!title){
alert("Enter task title");
return;
}
if(editId){
const t=tasks.find(t=>t.id===editId);
t.title=title;
t.date=date;
t.priority=priority;
}else{
tasks.push({
id:Date.now(),
title,
date,
priority,
status:currentStatus
});
}
closeModal();
renderTasks();
}
function editTask(id){
const task=tasks.find(t=>t.id===id);
editId=id;
document.getElementById("taskTitle").value=task.title;
document.getElementById("taskDate").value=task.date;
document.getElementById("taskPriority").value=task.priority;
document.getElementById("modal").style.display="flex";
}
function deleteTask(id){
tasks=tasks.filter(t=>t.id!==id);
renderTasks();
}
document.querySelectorAll(".task-list").forEach(list=>{
list.addEventListener("dragover",e=>e.preventDefault());
list.addEventListener("drop",e=>{
e.preventDefault();
const id=e.dataTransfer.getData("text");
const task=tasks.find(t=>t.id==id);
task.status=list.closest(".column").dataset.status;
renderTasks();
});
});
document.getElementById("themeToggle").addEventListener("click",()=>{
document.body.classList.toggle("dark");
});
renderTasks(); Related Projects
Day 4 : Invoice Generator
Creates invoices dynamically with item details and real-time total calculation.
Concepts: DOM manipulation, form handling, calculations, data rendering.
Day 5 : Chat UI (Frontend Only)
A simple chat interface with message sending and display functionality.
Concepts: DOM manipulation, event handling, dynamic UI updates.
Day 6 : File Upload Progress Bar
File upload interface with a visual progress bar and smooth animation.
Concepts: File API, progress tracking, animations, event handling.