Gantt
A read-only project timeline: tasks, groups, milestones and dependencies on a day, week or month scale.
c2-gantt
A read-only project timeline: tasks as bars on a day, week or month scale, with progress, groups that span their children, milestones, finish-to-start dependency arrows and a line for today. A task list sits on the left and stays put while the timeline scrolls sideways; below 560px of width it gives way to a compact layout with each label above its bar.
Tasks come in one of two ways. Give tasks an array (or a JSON attribute) for data from an API, or write
c2-gantt-task elements inside the chart, nested to form groups, for markup. When tasks holds an array it
wins and the children are ignored.
Dates are calendar days (YYYY-MM-DD), and end is inclusive. Weeks start on the locale's first day of the
week (locale, the page's lang, or the browser's language) unless week-start says otherwise, and the
locale's weekend is shaded.
The chart is a tree grid: each row is focusable, ↑ and ↓ move between rows, → and ← open and close groups, Enter selects. Each row's accessible name gives the task's dates, length, progress and predecessors.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
tasks | GanttTaskConfig[] | null | null | The tasks, as an array or a JSON attribute. null (the default) reads the c2-gantt-task children instead;
an array wins over them. Assign a new array to change the data. |
scale | GanttScale | week | Zoom level: day, week or month. |
start | string | undefined | — | First visible day, YYYY-MM-DD. Defaults to the tasks' first day, snapped to the scale. |
end | string | undefined | — | Last visible day, YYYY-MM-DD. Defaults to the tasks' last day, snapped to the scale. |
today | string | undefined | — | Where the today line goes: absent for the current date, a YYYY-MM-DD day to pin it, false to hide it. |
selected | string | null | null | Id of the selected task. |
collapsed | string[] | [] | Ids of the closed groups, separated by ; in the attribute. |
hide-list | boolean | false | Leaves the task list out and labels the bars instead. The rows stay available to assistive technology. |
layout | GanttLayout | auto | split keeps the task list, compact puts each label above its bar, auto picks compact below 560px. |
locale | string | undefined | — | Language of the dates and of the default week start. Defaults to the page's lang, then the browser's. |
week-start | string | locale | First day of the week: locale, monday … sunday, or an ISO number (1 is Monday, 7 is Sunday). |
weekend | string | undefined | — | ISO weekdays to shade, such as 6 7. Absent follows the locale; an empty value shades nothing. |
loading | boolean | false | Shows placeholder rows while the tasks load. |
aria-label | string | null | null | Accessible name of the chart. |
Slots
| Name | Description |
|---|---|
empty | Shown when there are no tasks. Defaults to "No tasks to show". |
list-header | Heading of the task list column. Defaults to "Task". |
duration-header | Heading of the duration column. Defaults to "Days". |
Events
| Name | Type | Description |
|---|---|---|
selection-change | CustomEvent<GanttSelectionChangeEventDetail> | Fired after the user selects a task. detail.value is its id. Does not bubble. |
group-toggle | CustomEvent<GanttGroupToggleEventDetail> | Fired after the user opens or closes a group. collapsed already holds the new state. Does not bubble. |
task-hover | CustomEvent<GanttTaskHoverEventDetail> | Fired when the pointer moves onto a bar, or off the bars (with nulls). Does not bubble. |
task-click | CustomEvent<GanttTaskEventDetail> | Fired when a bar or a row is clicked, or Enter is pressed on a row, before the selection changes. Cancel it to keep the selection as it is. Bubbles. |
CSS parts
Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.
| Name | Description |
|---|---|
base | The chart's frame. |
scroller | The scrolling area holding the list and the timeline. |
empty | Region wrapping the empty slot, shown only while there are no tasks. It styles the fallback text; assigned content keeps its own styles. |
row | A row of the task list. |
bar | A task's bar. |
progress | The completed share of a bar. |
milestone | A milestone's diamond. |
summary | A group's summary bar. |
link | A dependency arrow. |
today | The line for today. |
tooltip | The tooltip. |
CSS custom properties
Grouped by semantic target and state from --c2-<component>__<target>__<state>--<property>. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-gantt--background | color | #ffffff | Surface of the chart; bar tints are mixed against it. |
--c2-gantt--color | color | #18181b | |
--c2-gantt--font-family | font-family | inherit | |
--c2-gantt--font-size | font-size | 12px | |
--c2-gantt--border | border | 1px solid #e4e4e7 | |
--c2-gantt--border-radius | border-radius | 8px | |
--c2-gantt--max-height | pixel | none | Caps the height; the chart then scrolls vertically too, with the header pinned. |
--c2-gantt__header--background | color | #fafafa | |
--c2-gantt__header--color | color | #71717a | |
--c2-gantt__header--height | pixel | 48px | Both tiers of the scale together. |
--c2-gantt__header__major--color | color | #18181b | Month or year labels. |
--c2-gantt__header__major--font-weight | font-weight | 600 | |
--c2-gantt__header__today--color | color | rgb(2, 101, 220) | Today's day number on the day scale. |
--c2-gantt__list--width | pixel | 260px | |
--c2-gantt__list--border-right | border | 1px solid #e4e4e7 | |
--c2-gantt__list--indent | pixel | 16px | Indent per nesting level. |
--c2-gantt__list__group--font-weight | font-weight | 600 | |
--c2-gantt__list__duration--color | color | #71717a | |
--c2-gantt__row--height | pixel | 32px | |
--c2-gantt__row--border-bottom | border | 1px solid #e4e4e7 | |
--c2-gantt__row__hover--background | color | #f4f4f5 | |
--c2-gantt__row__selected--background | color | rgba(2, 101, 220, 0.08) | |
--c2-gantt__row__focus--outline | outline | 2px solid rgba(2, 101, 220, 0.4) | |
--c2-gantt__row-compact--height | pixel | 44px | Row height of the compact layout, which adds a label line. |
--c2-gantt__grid-line--color | color | #e4e4e7 | |
--c2-gantt__weekend--background | color | #fafafa | |
--c2-gantt__column-day--width | pixel | 28px | Width of one day on the day scale. |
--c2-gantt__column-week--width | pixel | 16px | Width of one day on the week scale. |
--c2-gantt__column-month--width | pixel | 5px | Width of one day on the month scale. |
--c2-gantt__bar--height | pixel | 20px | |
--c2-gantt__bar--color | color | rgb(2, 101, 220) | Hue of a bar without a tone; its fill, border and progress are mixed from it. |
--c2-gantt__bar--background-mix | percentage | 16% | |
--c2-gantt__bar--border-mix | percentage | 45% | |
--c2-gantt__bar--border-radius | border-radius | 6px | |
--c2-gantt__bar--font-weight | font-weight | 500 | |
--c2-gantt__bar__selected--outline-width | pixel | 2px | |
--c2-gantt__bar-compact--height | pixel | 14px | |
--c2-gantt__progress--background-mix | percentage | 36% | |
--c2-gantt__label--color | color | #71717a | Labels drawn beside a bar too short to hold them. |
--c2-gantt__summary--color | color | #18181b | |
--c2-gantt__summary--height | pixel | 6px | |
--c2-gantt__milestone--size | pixel | 12px | |
--c2-gantt__milestone--color | color | #18181b | |
--c2-gantt__link--color | color | #a1a1aa | |
--c2-gantt__link--width | pixel | 1.25px | |
--c2-gantt__link__active--color | color | rgb(2, 101, 220) | Links of the selected or hovered task. |
--c2-gantt__today--color | color | #dc2626 | |
--c2-gantt__today--width | pixel | 2px | |
--c2-gantt__tooltip--background | color | #ffffff | |
--c2-gantt__tooltip--color | color | #18181b | |
--c2-gantt__tooltip--muted-color | color | #71717a | |
--c2-gantt__tooltip--border | border | 1px solid #d4d4d8 | |
--c2-gantt__tooltip--border-radius | border-radius | 8px | |
--c2-gantt__tooltip--box-shadow | box-shadow | 0 8px 24px rgba(24, 24, 27, 0.08) | |
--c2-gantt__tooltip--width | pixel | 240px | |
--c2-gantt__tone-success--color | color | #15803d | |
--c2-gantt__tone-warning--color | color | #a16207 | |
--c2-gantt__tone-danger--color | color | #dc2626 | |
--c2-gantt__tone-neutral--color | color | #71717a | |
--c2-gantt__series-1--color | color | #0265dc | tone: 1; the eight slots match the chart palette. |
--c2-gantt__series-2--color | color | #ea580c | |
--c2-gantt__series-3--color | color | #0f766e | |
--c2-gantt__series-4--color | color | #db2777 | |
--c2-gantt__series-5--color | color | #a16207 | |
--c2-gantt__series-6--color | color | #7c3aed | |
--c2-gantt__series-7--color | color | #0891b2 | |
--c2-gantt__series-8--color | color | #52525b | |
--c2-gantt__skeleton--background | color | #f4f4f5 | |
--c2-gantt__empty--color | color | #71717a | |
--c2-gantt__empty--padding | padding | 32px 16px | |
c2-gantt-task
One task of a c2-gantt, declared in markup. The element renders nothing: it is a definition the chart reads,
the way c2-chart-series is for a chart. A task nested inside another task is that task's child, so the
markup is the tree:
<c2-gantt>
<c2-gantt-task task-id="design" label="Design">
<c2-gantt-task task-id="ia" start="2026-09-28" end="2026-10-02">Information architecture</c2-gantt-task>
<c2-gantt-task start="2026-10-05" end="2026-10-16" dependencies="ia">Visual design</c2-gantt-task>
</c2-gantt-task>
</c2-gantt>
The label is the label attribute, or the element's own text when there is none. Wrapper elements between
tasks (an Astro island, a template's container) are looked through.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
task-id | string | undefined | — | Id other tasks name in dependencies. Falls back to the element's id, then to a generated key. |
label | string | undefined | — | Text in the task list, the bar and the tooltip. Falls back to the element's own text. |
start | string | undefined | — | First day, YYYY-MM-DD. Ignored on a task with children, whose span is theirs. |
end | string | undefined | — | Last day, YYYY-MM-DD, inclusive. Omitted means a one-day task. |
progress | number | undefined | — | Share of the work done, from 0 to 1. |
milestone | boolean | false | Draws the task as a diamond on its start day. |
dependencies | string | undefined | — | Ids of the tasks that must finish first, separated by spaces. |
tone | string | undefined | — | primary, success, warning, danger, neutral, or a palette slot from 1 to 8. |