Created
March 29, 2025 00:11
-
-
Save ibuilder/a66a3d29eae0c74459bdc1dfceb232a6 to your computer and use it in GitHub Desktop.
This Gantt chart for a house building project includes: Task Information: Each task has a name, start date, end date, and calculated duration Tasks are displayed chronologically from site preparation to final inspection Key Milestones as requested: Foundation Complete (May 10, 2025) Building Top Out (June 25, 2025) Building Closeout (October 5, …
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>House Building Project Gantt Chart</title> | |
<!-- Bootstrap CSS --> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet"> | |
<style> | |
.gantt-container { | |
overflow-x: auto; | |
margin-top: 20px; | |
} | |
.gantt-row { | |
height: 40px; | |
border-bottom: 1px solid #e0e0e0; | |
display: flex; | |
align-items: center; | |
} | |
.gantt-header { | |
background-color: #f8f9fa; | |
font-weight: bold; | |
border-bottom: 2px solid #dee2e6; | |
} | |
.gantt-labels { | |
width: 300px; | |
background-color: white; | |
position: sticky; | |
left: 0; | |
z-index: 10; | |
padding-right: 10px; | |
border-right: 2px solid #dee2e6; | |
} | |
.gantt-chart { | |
position: relative; | |
display: flex; | |
flex-grow: 1; | |
} | |
.day-column { | |
min-width: 30px; | |
text-align: center; | |
border-right: 1px solid #f0f0f0; | |
} | |
.weekend { | |
background-color: #f8f9fa; | |
} | |
.bar { | |
position: absolute; | |
height: 24px; | |
border-radius: 4px; | |
background-color: #007bff; | |
z-index: 5; | |
} | |
.milestone { | |
position: absolute; | |
width: 0; | |
height: 0; | |
border-left: 10px solid transparent; | |
border-right: 10px solid transparent; | |
border-bottom: 20px solid #dc3545; | |
z-index: 6; | |
} | |
.milestone-label { | |
position: absolute; | |
font-size: 12px; | |
font-weight: bold; | |
color: #dc3545; | |
white-space: nowrap; | |
top: -20px; | |
} | |
.task-dates { | |
font-size: 12px; | |
color: #666; | |
} | |
.header-sticky { | |
position: sticky; | |
top: 0; | |
z-index: 20; | |
background-color: #f8f9fa; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container-fluid mt-3"> | |
<h1 class="text-center mb-4">House Building Project Schedule</h1> | |
<div class="row"> | |
<div class="col-md-12"> | |
<div class="card"> | |
<div class="card-header bg-primary text-white"> | |
<h4 class="mb-0">Gantt Chart Timeline</h4> | |
</div> | |
<div class="card-body"> | |
<div class="gantt-container" id="gantt-container"> | |
<!-- Gantt chart will be rendered here by JavaScript --> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="row mt-4"> | |
<div class="col-md-12"> | |
<div class="card"> | |
<div class="card-header bg-primary text-white"> | |
<h4 class="mb-0">Project Information</h4> | |
</div> | |
<div class="card-body"> | |
<div class="row"> | |
<div class="col-md-6"> | |
<h5>Project Details</h5> | |
<p><strong>Project Name:</strong> Custom House Build</p> | |
<p><strong>Start Date:</strong> <span id="project-start-date"></span></p> | |
<p><strong>End Date:</strong> <span id="project-end-date"></span></p> | |
<p><strong>Total Duration:</strong> <span id="project-duration"></span> days</p> | |
</div> | |
<div class="col-md-6"> | |
<h5>Legend</h5> | |
<div class="d-flex align-items-center mb-2"> | |
<div style="width: 50px; height: 20px; background-color: #007bff; border-radius: 4px;"></div> | |
<span class="ms-2">Task</span> | |
</div> | |
<div class="d-flex align-items-center"> | |
<div style="width: 0; height: 0; border-left: 10px solid transparent; border-right: 10px solid transparent; border-bottom: 20px solid #dc3545;"></div> | |
<span class="ms-2">Milestone</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Bootstrap and JavaScript --> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// Project data | |
const tasks = [ | |
{ | |
id: 1, | |
name: "Site Preparation", | |
start: "2025-04-01", | |
end: "2025-04-10", | |
milestone: false | |
}, | |
{ | |
id: 2, | |
name: "Excavation", | |
start: "2025-04-11", | |
end: "2025-04-18", | |
milestone: false | |
}, | |
{ | |
id: 3, | |
name: "Foundation", | |
start: "2025-04-19", | |
end: "2025-05-10", | |
milestone: false | |
}, | |
{ | |
id: 4, | |
name: "Foundation Complete", | |
start: "2025-05-10", | |
end: "2025-05-10", | |
milestone: true | |
}, | |
{ | |
id: 5, | |
name: "Framing", | |
start: "2025-05-11", | |
end: "2025-06-05", | |
milestone: false | |
}, | |
{ | |
id: 6, | |
name: "Roofing", | |
start: "2025-06-06", | |
end: "2025-06-20", | |
milestone: false | |
}, | |
{ | |
id: 7, | |
name: "Window & Door Installation", | |
start: "2025-06-15", | |
end: "2025-06-25", | |
milestone: false | |
}, | |
{ | |
id: 8, | |
name: "Building Top Out", | |
start: "2025-06-25", | |
end: "2025-06-25", | |
milestone: true | |
}, | |
{ | |
id: 9, | |
name: "Plumbing Rough-In", | |
start: "2025-06-26", | |
end: "2025-07-10", | |
milestone: false | |
}, | |
{ | |
id: 10, | |
name: "Electrical Rough-In", | |
start: "2025-07-01", | |
end: "2025-07-15", | |
milestone: false | |
}, | |
{ | |
id: 11, | |
name: "HVAC Installation", | |
start: "2025-07-05", | |
end: "2025-07-20", | |
milestone: false | |
}, | |
{ | |
id: 12, | |
name: "Insulation", | |
start: "2025-07-21", | |
end: "2025-07-28", | |
milestone: false | |
}, | |
{ | |
id: 13, | |
name: "Drywall", | |
start: "2025-07-29", | |
end: "2025-08-15", | |
milestone: false | |
}, | |
{ | |
id: 14, | |
name: "Interior Painting", | |
start: "2025-08-16", | |
end: "2025-08-30", | |
milestone: false | |
}, | |
{ | |
id: 15, | |
name: "Flooring Installation", | |
start: "2025-08-25", | |
end: "2025-09-10", | |
milestone: false | |
}, | |
{ | |
id: 16, | |
name: "Cabinet Installation", | |
start: "2025-09-11", | |
end: "2025-09-20", | |
milestone: false | |
}, | |
{ | |
id: 17, | |
name: "Appliance Installation", | |
start: "2025-09-21", | |
end: "2025-09-25", | |
milestone: false | |
}, | |
{ | |
id: 18, | |
name: "Fixture Installation", | |
start: "2025-09-26", | |
end: "2025-10-05", | |
milestone: false | |
}, | |
{ | |
id: 19, | |
name: "Building Closeout", | |
start: "2025-10-05", | |
end: "2025-10-05", | |
milestone: true | |
}, | |
{ | |
id: 20, | |
name: "Final Inspection", | |
start: "2025-10-06", | |
end: "2025-10-10", | |
milestone: false | |
}, | |
{ | |
id: 21, | |
name: "Final Punchlist", | |
start: "2025-10-10", | |
end: "2025-10-10", | |
milestone: true | |
} | |
]; | |
// Calculate project duration | |
const startDate = new Date(tasks.reduce((min, task) => { | |
return new Date(task.start) < new Date(min) ? task.start : min; | |
}, tasks[0].start)); | |
const endDate = new Date(tasks.reduce((max, task) => { | |
return new Date(task.end) > new Date(max) ? task.end : max; | |
}, tasks[0].end)); | |
// Display project info | |
document.getElementById('project-start-date').textContent = formatDate(startDate); | |
document.getElementById('project-end-date').textContent = formatDate(endDate); | |
const projectDuration = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24)) + 1; | |
document.getElementById('project-duration').textContent = projectDuration; | |
// Generate dates for the chart | |
const dates = []; | |
const currentDate = new Date(startDate); | |
while (currentDate <= endDate) { | |
dates.push(new Date(currentDate)); | |
currentDate.setDate(currentDate.getDate() + 1); | |
} | |
// Build the gantt chart | |
buildGanttChart(tasks, dates, startDate); | |
}); | |
function buildGanttChart(tasks, dates, startDate) { | |
const container = document.getElementById('gantt-container'); | |
// Create header | |
const headerRow = document.createElement('div'); | |
headerRow.className = 'gantt-row gantt-header header-sticky'; | |
const headerLabels = document.createElement('div'); | |
headerLabels.className = 'gantt-labels'; | |
headerLabels.innerHTML = '<div class="ps-3">Task Name</div>'; | |
headerRow.appendChild(headerLabels); | |
const headerChart = document.createElement('div'); | |
headerChart.className = 'gantt-chart'; | |
// Add date headers | |
dates.forEach((date, index) => { | |
const dayCol = document.createElement('div'); | |
dayCol.className = 'day-column'; | |
// Check if it's a weekend | |
const day = date.getDay(); | |
if (day === 0 || day === 6) { | |
dayCol.classList.add('weekend'); | |
} | |
// Display date format depending on the day | |
if (date.getDate() === 1 || index === 0) { | |
// First day of month or first day in chart - show month/day | |
dayCol.innerHTML = `${date.getMonth() + 1}/${date.getDate()}`; | |
} else { | |
// Just the day | |
dayCol.innerHTML = date.getDate(); | |
} | |
headerChart.appendChild(dayCol); | |
}); | |
headerRow.appendChild(headerChart); | |
container.appendChild(headerRow); | |
// Create task rows | |
tasks.forEach(task => { | |
const row = document.createElement('div'); | |
row.className = 'gantt-row'; | |
const taskLabels = document.createElement('div'); | |
taskLabels.className = 'gantt-labels'; | |
// Task name and dates | |
const taskName = document.createElement('div'); | |
taskName.className = 'd-flex flex-column ps-3'; | |
taskName.innerHTML = ` | |
<div>${task.name}</div> | |
<div class="task-dates"> | |
${task.milestone ? 'Milestone' : formatDate(new Date(task.start)) + ' - ' + formatDate(new Date(task.end))} | |
${task.milestone ? '' : ' (' + calculateDuration(task.start, task.end) + ' days)'} | |
</div> | |
`; | |
taskLabels.appendChild(taskName); | |
row.appendChild(taskLabels); | |
const taskChart = document.createElement('div'); | |
taskChart.className = 'gantt-chart'; | |
// Add day columns for reference | |
dates.forEach(date => { | |
const dayCol = document.createElement('div'); | |
dayCol.className = 'day-column'; | |
// Check if it's a weekend | |
const day = date.getDay(); | |
if (day === 0 || day === 6) { | |
dayCol.classList.add('weekend'); | |
} | |
taskChart.appendChild(dayCol); | |
}); | |
// Add the task bar or milestone | |
if (task.milestone) { | |
// Milestone diamond | |
const milestone = document.createElement('div'); | |
milestone.className = 'milestone'; | |
const taskStartDate = new Date(task.start); | |
const daysDiff = Math.ceil((taskStartDate - startDate) / (1000 * 60 * 60 * 24)); | |
milestone.style.left = `${daysDiff * 30 + 15 - 10}px`; // 30px per day, centered | |
milestone.style.top = '10px'; | |
// Add milestone label | |
const milestoneLabel = document.createElement('div'); | |
milestoneLabel.className = 'milestone-label'; | |
milestoneLabel.textContent = task.name; | |
milestoneLabel.style.left = `${daysDiff * 30 + 15}px`; // 30px per day, centered | |
taskChart.appendChild(milestone); | |
taskChart.appendChild(milestoneLabel); | |
} else { | |
// Task bar | |
const bar = document.createElement('div'); | |
bar.className = 'bar'; | |
const taskStartDate = new Date(task.start); | |
const taskEndDate = new Date(task.end); | |
const daysDiff = Math.ceil((taskStartDate - startDate) / (1000 * 60 * 60 * 24)); | |
const duration = calculateDuration(task.start, task.end); | |
bar.style.left = `${daysDiff * 30}px`; // 30px per day | |
bar.style.width = `${duration * 30}px`; | |
bar.style.top = '8px'; | |
taskChart.appendChild(bar); | |
} | |
row.appendChild(taskChart); | |
container.appendChild(row); | |
}); | |
} | |
function formatDate(date) { | |
return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`; | |
} | |
function calculateDuration(start, end) { | |
const startDate = new Date(start); | |
const endDate = new Date(end); | |
return Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24)) + 1; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment