Gantt Chart Table — Free HTML CSS JS Snippet

Gantt Chart Table · Tables · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

CSS Grid: 160px label column + 1fr bar area — no table element
Horizontal bars: position:absolute, left% = start%, width% = duration%
Month dividers: repeating-linear-gradient at 33.33% — no extra HTML elements
Today line: JS-computed left% from current date within the quarter range
Colour-coded bars: one colour per team for visual team separation
Repeating background grid on .g-bars for month column visual alignment
Responsive: overflow-x:auto on container — horizontal scroll on narrow screens
Zero chart library — pure CSS and 10 lines of JavaScript

About this UI Snippet

Gantt Chart Table — CSS Grid Layout, Horizontal Bars, Month Dividers & Today Indicator

Screenshot of the Gantt Chart Table snippet rendered live

A Gantt chart table visualises project tasks as horizontal bars across a timeline, making it easy to see task durations, overlaps, and the overall project schedule at a glance. This snippet provides a complete CSS-based Gantt chart without any chart library: a two-column CSS Grid (task labels + bar area), horizontal bars positioned with left and width percentages, three-column month dividers via repeating-linear-gradient grid lines, colour-coded bars per team, and a JavaScript-positioned "Today" indicator line.

The CSS Grid layout

The gantt-grid uses display: grid; grid-template-columns: 160px 1fr. The left column is a fixed 160px for task labels; the right column fills the remaining space for the bar chart area. Each row pair (label + bars) repeats the two-column pattern. The header row uses .g-label-head and .g-months, which itself uses grid-template-columns: repeat(3,1fr) to show three equal-width month columns.

Horizontal bar positioning

Each .g-bar uses position: absolute within a position: relative .g-bars container. The left CSS property positions the bar's start as a percentage of the container width. The width property controls the bar's duration as a percentage. For a 3-month view (90 days): a task starting on April 20 (day 20 of 90) has left: 20/90*100 ≈ 22%. A task lasting 40 days has width: 40/90*100 ≈ 44%. The data-tip attributes hold human-readable date labels for tooltips.

Month column gridlines

The .g-bars background uses repeating-linear-gradient(90deg, transparent, transparent calc(33.33% - 1px), #f1f5f9 calc(33.33% - 1px), #f1f5f9 33.33%). This draws a 1px grey line at every 33.33% (one-third = one month of three) purely in CSS — no extra HTML elements needed for the vertical grid lines.

The today indicator line

A JavaScript snippet computes the current date's position within the Q2 range (April 1 – June 30). If today falls within the range, the percentage through the quarter is computed and the today-line div is positioned accordingly. The line has a red background and a ::before pseudo-element showing "Today" as a label above it.

Colour-coded bars by team

Engineering bars use indigo, Design uses pink, Marketing uses green, Product uses amber. The legend at the top maps each colour to its team. This visual separation lets viewers scan which team is responsible for each task without reading the label.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to work out the percentage math by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how the repeating-linear-gradient on the bars container draws the month gridlines at precisely 33.33% intervals without any extra DOM elements, and why the today-line's left offset uses a calc() expression combining a fixed 160px with a percentage of the remaining width rather than a single percentage value. The same assistant can help optimize it — ask whether computing each bar's left and width from raw dates on every render is worth memoizing once tasks come from a real API instead of hardcoded inline styles, or whether the grid-template-columns fixed-160px approach holds up with much longer task labels. It's also useful for extending the chart: have it add dependency arrows between related tasks drawn with an absolutely-positioned SVG overlay, a zoom toggle between month and week views, or drag-to-resize on the bars themselves to adjust task duration interactively. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a Gantt chart as a CSS Grid table in plain HTML, CSS, and JavaScript — no chart library, no canvas or SVG for the bars themselves.

Requirements:
- A two-column CSS Grid layout: a fixed-width label column on the left and a flexible bar-area column on the right, repeated for a header row (task label header plus month headers in their own sub-grid of equal columns) followed by one label/bar-area row pair per task.
- Each task's bar must be an absolutely-positioned element inside a relatively-positioned bar-area container, with its left offset and width expressed as percentages representing, respectively, how far into the total date range the task starts and what fraction of the total range its duration spans.
- Draw the vertical month-boundary gridlines behind the bars using only a CSS repeating-linear-gradient background on the bar-area container (computing the correct repeat interval for the number of month columns), not extra divs or an SVG grid.
- Compute today's position as a percentage of the overall date range in JavaScript by comparing the current date against a defined range-start and range-end, and position a vertical "today" indicator line at that percentage — but expressed relative to the bar-area only, meaning the line's actual left offset must account for the fixed-width label column in addition to the percentage into the bar area. Do not render the line at all if today falls outside the defined range.
- Give every bar a data attribute holding a human-readable date range and color-code bars by team/category, with a legend mapping each color to its team.
- Make the whole table horizontally scrollable on narrow viewports by giving the grid a sensible minimum width inside an overflow-x auto container, without breaking the today-line's percentage-based positioning.

Step by step

How to Use

  1. 1
    Review the Gantt chart and today lineThe chart shows 8 tasks across a 3-month quarter. The red "Today" line positions itself based on the current date within the April–June range. If today is outside the range, the line does not appear.
  2. 2
    Update task names and bar positionsEdit each .g-label div text for the task name. Update the .g-bar style: left% is the task start as a percentage of the total period; width% is the task duration as a percentage. Add data-tip for a human-readable date range.
  3. 3
    Add or remove task rowsEach task is a pair of divs: .g-label and .g-bars. Duplicate both divs to add a new task row. Delete both to remove one. The grid auto-expands vertically for new rows.
  4. 4
    Change the time rangeUpdate Q2_START and Q2_END in the JS to your project start and end dates. Update the month headers in .g-months. Recalculate bar left and width percentages as (taskStart - rangeStart) / rangeDuration * 100.
  5. 5
    Add a tooltip on bar hoverEach .g-bar has data-tip="Apr 1 – May 7". Add a mouseover listener: document.querySelectorAll(".g-bar").forEach(b => b.title = b.dataset.tip). Or implement a custom tooltip using the CSS Tooltip snippet.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component mapping a tasks array to bar divs, or "Tailwind" for a Tailwind CSS version.

Real-world uses

Common Use Cases

Product roadmap and quarterly planning charts
The Q2 roadmap structure maps directly to product planning use cases — pair it with the product roadmap card for a now/next/later view. Update the task names to your actual roadmap items, colour-code by team or epic, and set bar positions from your planned start and end dates as percentages of the quarter.
Sprint and project timeline dashboards
Show sprint tasks, milestones, and deliverables on a Gantt chart within a dashboard, alongside a kanban board for status. The today line shows current progress. Bars that have not started appear to the right of today; completed bars appear to the left.
Agency project and campaign timeline views
Use for multi-phase agency projects: discovery, design, development, launch. Colour-code by project phase or client. The three-month view covers the typical agency project engagement duration.
Generate Gantt bars programmatically from project data
Fetch project tasks from an API and compute bar positions: left = (task.startDate - rangeStart) / rangeDuration * 100; width = task.durationDays / rangeDays * 100. Render the .g-label and .g-bar divs from the computed values.
Study CSS positioning and percentage layout techniques
The Gantt bars demonstrate how position:absolute with left and width percentages creates a scalable, responsive timeline. The repeating-linear-gradient technique shows how to draw grid lines purely in CSS without any additional DOM elements.
Content calendar and editorial planning views
Map content types (blog posts, videos, emails, social) to rows with colour-coded bars. The bar duration represents the production and publication window. The today line marks current progress through the editorial calendar.

Got questions?

Frequently Asked Questions

First define your range: const rangeStart = new Date("2026-04-01"); const rangeDays = 91 (April-June = 91 days). For each task: const taskStart = new Date(task.startDate); const taskDuration = task.durationDays; const left = (taskStart - rangeStart) / (86400000 * rangeDays) * 100; const width = taskDuration / rangeDays * 100. Apply these as inline styles: bar.style.left = left.toFixed(1) + "%"; bar.style.width = width.toFixed(1) + "%".

Add an SVG overlay on top of the .gantt-scroll with position:absolute; inset:0; pointer-events:none. For each dependency, draw an SVG path from the right edge of the predecessor bar to the left edge of the successor bar. The path can be a simple elbow: M x1 y1 L x2 y1 L x2 y2 L x3 y2 where x1/y1 is the predecessor end and x3/y2 is the successor start. This requires JavaScript to compute bar positions from the DOM.

The .gantt-scroll already has overflow-x: auto. For a 12-month view, change .g-months to grid-template-columns: repeat(12,1fr) and update the month labels. Change the repeating-linear-gradient to 8.33% (1/12). Set a minimum width on .gantt-grid: min-width: 1200px. Bar percentages automatically span the correct portion of the 12-month view.

Click "JSX" to download. Define a tasks array: [{name, team, start, end, color}]. Define rangeStart and rangeEnd dates. Compute left and width for each task with useMemo. Map tasks to pairs of label div + bar div. Compute the today line position in a useEffect that runs once on mount. For dependencies, manage them as a separate array of {from, to} task index pairs.