Build A Drag & Drop Kanban Board using HTML CSS & JavaScript
Last Updated :
13 Mar, 2024
A Kanban board is a project management tool designed to visualize work, limit work in progress, and maximize efficiency. With drag & drop functionality, users can easily move tasks between different stages of completion, providing a visual representation of the workflow.
Final OutputApproach:
The below defined steps can be utilised to build and design a Kanban board layout:
- In the first step, we will create a folder with the project name and create the HTML, CSS, JavaScript files.
- Now, use the different HTML tags like header, meta, title, head, div, input, img logo etc to structure the web page.
- Style the different components and the elements of HTML responsively to make the page attractive for every device using CSS.
- To define the responsive styles, Adjust the width of the containers in %.
- Use JavaScript to add interactivity, including drag and drop functionality.
- Add functionality to allow users to add, edit, and delete tasks.
Example: This example describes the basic implementation of the Drag & Drop Kanban Board using HTML, CSS, and JavaScript.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<title>Kanban Board</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href=
"https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap">
</head>
<body>
<div class="head">
<img src=
"https://media.geeksforgeeks.org/gfg-gg-logo.svg">
<h1>Kanban Board</h1>
</div>
<div class="board">
<div class="column" id="todo" ondrop="drop(event, 'todo')"
ondragover="allowDrop(event)">
<h2>Todo</h2>
<hr>
<div class="tasks-in-btn">
<input type="text" id="taskInput" class="task-input"
placeholder="Enter a task..."
oninput="capitalizeInput(this)">
<button class="add-task-btn" onclick="addTask('todo')">
Add Task
</button>
</div>
<div class="task-container"></div>
</div>
<div class="column" id="in-progress"
ondrop="drop(event, 'in-progress')"
ondragover="allowDrop(event)">
<h2>In Progress</h2>
<hr>
<div class="task-container"></div>
</div>
<div class="column" id="done"
ondrop="drop(event, 'done')"
ondragover="allowDrop(event)">
<h2>Done</h2>
<hr>
<div class="task-container"></div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS
/* style.css */
body {
font-family: 'Roboto', sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 0;
}
.head {
background-color: #1976d2;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
box-shadow:
0px 2px 5px rgba(0, 0, 0, 0.1);
}
.head img {
width: 50px;
margin-right: 10px;
}
.head h1 {
font-size: 24px;
margin: 0;
}
.board {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
padding: 20px;
}
.column {
/* width: 30%; */
width: calc(100% - 30px);
max-width: 400px;
margin: 10px;
background-color: #fff;
border-radius: 10px;
padding: 20px;
box-shadow:
0px 2px 5px rgba(0, 0, 0, 0.1);
}
.column h2 {
font-size: 18px;
margin-bottom: 10px;
color: #333;
}
.task-input {
width: 60%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 10px;
}
.task {
background-color: #e0e0e0;
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
cursor: move;
}
.delete-btn {
float: right;
cursor: pointer;
}
.add-task-btn {
background-color: #4caf50;
border: none;
color: white;
/* Adjust padding to make
the button smaller */
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 14px;
/* Decrease font size */
border-radius: 5px;
/* Adjust border radius
for a softer look */
cursor: pointer;
transition: background-color 0.3s;
}
.add-task-btn:hover {
background-color: #45a049;
}
#todo .task {
background-color: #b3e5fc;
/* Light blue */
}
#in-progress .task {
background-color: #ffcdd2;
/* Light pink */
}
#done .task {
background-color: #c8e6c9;
/* Light green */
}
.task {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
margin-bottom: 5px;
cursor: move;
}
.delete-btn {
float: right;
cursor: pointer;
}
.tasks-in-btn {
display: flex;
justify-content: space-around;
margin-bottom: 3px;
}
JavaScript
//script.js
let tasks = JSON.parse
(localStorage.getItem('tasks')) || [];
document.addEventListener
("DOMContentLoaded", function () {
renderTasks();
});
// Function to render tasks on the board
function renderTasks() {
const columns =
['todo', 'in-progress', 'done'];
columns.forEach(columnId => {
const column =
document.getElementById(columnId);
column.querySelector('.task-container').
innerHTML = '';
tasks.forEach(task => {
if (task.status === columnId) {
const taskElement =
createTaskElement(task.content, task.id);
column.querySelector('.task-container').
appendChild(taskElement);
}
});
});
}
function createTaskElement(content, id) {
const taskId = id
const task = document.createElement("div");
task.id = taskId;
task.className = "task";
task.draggable = true;
task.innerHTML =
`${content}
<span class="delete-btn"
onclick="deleteTask('${taskId}')">
❌
</span>`;
task.addEventListener("dragstart", drag);
return task;
}
// Function to delete a task
function deleteTask(taskId) {
tasks = tasks.
filter(task => task.id !== taskId);
updateLocalStorage();
renderTasks();
}
function allowDrop(event) {
event.preventDefault();
}
function drag(event) {
event.dataTransfer.
setData("text/plain", event.target.id);
}
function drop(event, columnId) {
event.preventDefault();
console.log(columnId)
const data = event.
dataTransfer.getData("text/plain");
const draggedElement =
document.getElementById(data);
console.log(draggedElement)
if (draggedElement) {
const taskStatus = columnId;
updateTaskStatus(data, taskStatus);
event.target.querySelector('.task-container').
appendChild(draggedElement);
}
}
function capitalizeInput(input) {
input.value = input.value.toUpperCase();
}
function addTask(columnId) {
const taskInput =
document.getElementById('taskInput');
const taskContent = taskInput.value.trim();
if (taskContent !== "") {
const newTask = {
id: "task-" + Date.now(),
content: taskContent,
status: columnId
};
tasks.push(newTask);
updateLocalStorage();
renderTasks();
taskInput.value = "";
}
}
// Function to update task status
// when moved to another column
function updateTaskStatus(taskId, newStatus) {
console.log(newStatus)
tasks = tasks.map(task => {
console.log(task)
console.log(taskId)
if (task.id === taskId) {
console.log("inside if")
return { ...task, status: newStatus };
}
return task;
});
updateLocalStorage();
}
// Function to update local
// storage with current tasks
function updateLocalStorage() {
console.log("task update")
localStorage.setItem
('tasks', JSON.stringify(tasks));
}
Output:
final output gif
Similar Reads
Drag and Drop Sortable List Using HTML CSS & JavaScript The Drag and Drop Sortable List Project in JavaScript allows users to easily reorder items in a list using drag-and-drop functionality. This interactive tool enhances user experience by enabling smooth, dynamic list organization, ideal for applications like task managers or shopping lists.What we ar
5 min read
Create A Draggable Card Slider in HTML CSS & JavaScript In this article, we will demonstrate how to create a draggable card slider using HTML, CSS, and JavaScript. We'll use a GeeksforGeeks card slider as an example and implement the functionality to slide cards left and right using arrow buttons. Additionally, we'll incorporate the draggable option, all
5 min read
Create a Minesweeper Game using HTML CSS & JavaScript Minesweeper is a classic puzzle game that challenges your logical thinking and deduction skills. It's a great project for developers looking to improve their front-end web development skills. In this article, we'll walk through the steps to create a Minesweeper game using HTML, CSS, and JavaScript.
4 min read
script.aculo.us Drag & Drop snap Option The snap option in the script.aculo.us Drag and Drop module is used to make a draggable element snap to a grid or constrain its movement in the defined space. It is set to false by default. It can be defined with a single value or a function that will define the places where the element would snap.
1 min read
Drag and Drop List Using TypeScript A drag-and-drop sortable list in TypeScript lets users reorder items by dragging them to new positions. This is done using dragstart, dragend and dragover events for smooth DOM manipulation.What Weâre Going to CreateWeâll build a drag-and-drop sortable list with features like handling dragstart, dra
5 min read
Create a Draggable Bottom Sheet Modal in HTML CSS & JavaScript In this article, we'll create a versatile draggable bottom sheet modal using HTML, CSS, and JavaScript. A bottom sheet modal is a UI component that can be dragged up or down to reveal or hide content. We'll cover the entire process of creating this interactive element, which can be useful for variou
3 min read