Creating a Basic Gantt Chart

This page walks through building a Gantt chart from scratch using ApexGantt: starting with a flat list of tasks, adding a hierarchy, then adding dependencies between tasks.

If you have not installed ApexGantt yet, see Installation & Usage.

A flat task list

The minimum chart requires an array of tasks, each with an id, name, startTime, and endTime.

<div id="gantt" style="height: 300px;"></div>
import ApexGantt from 'apexgantt'

ApexGantt.setLicense('YOUR-LICENSE-KEY')

const gantt = new ApexGantt(document.getElementById('gantt'), {
  inputDateFormat: 'YYYY-MM-DD', // the dates below are ISO; the default is 'MM-DD-YYYY'
  series: [
    { id: '1', name: 'Discovery',   startTime: '2024-04-01', endTime: '2024-04-07' },
    { id: '2', name: 'Design',      startTime: '2024-04-08', endTime: '2024-04-20' },
    { id: '3', name: 'Development', startTime: '2024-04-21', endTime: '2024-05-10' },
    { id: '4', name: 'Testing',     startTime: '2024-05-06', endTime: '2024-05-15' },
    { id: '5', name: 'Launch',      startTime: '2024-05-16', endTime: '2024-05-17' },
  ],
})

gantt.render()

ApexGantt draws a bar for each task spanning its start and end dates, with a task list panel on the left showing the task names.

Adding progress

Set progress (0-100) on any task to render a filled segment inside the bar.

series: [
  { id: '1', name: 'Discovery',   startTime: '2024-04-01', endTime: '2024-04-07', progress: 100 },
  { id: '2', name: 'Design',      startTime: '2024-04-08', endTime: '2024-04-20', progress: 75 },
  { id: '3', name: 'Development', startTime: '2024-04-21', endTime: '2024-05-10', progress: 20 },
  { id: '4', name: 'Testing',     startTime: '2024-05-06', endTime: '2024-05-15', progress: 0 },
]

Adding a hierarchy

Link tasks to a parent by setting parentId to the parent's id. The parent row becomes a summary bar that auto-spans the earliest start to the latest end of its children.

series: [
  // Parent (summary) rows
  { id: 'p1', name: 'Phase 1: Research', startTime: '2024-04-01', endTime: '2024-04-14', progress: 100 },

  // Children
  { id: 'c1', name: 'Stakeholder interviews', startTime: '2024-04-01', endTime: '2024-04-05', parentId: 'p1', progress: 100 },
  { id: 'c2', name: 'Competitive analysis',   startTime: '2024-04-03', endTime: '2024-04-10', parentId: 'p1', progress: 100 },
  { id: 'c3', name: 'Requirements doc',       startTime: '2024-04-08', endTime: '2024-04-14', parentId: 'p1', progress: 100 },

  // Second phase
  { id: 'p2', name: 'Phase 2: Design', startTime: '2024-04-15', endTime: '2024-04-30', progress: 50 },
  { id: 'c4', name: 'Wireframes',      startTime: '2024-04-15', endTime: '2024-04-22', parentId: 'p2', progress: 100 },
  { id: 'c5', name: 'Visual design',   startTime: '2024-04-20', endTime: '2024-04-30', parentId: 'p2', progress: 20 },
]

The hierarchy can be nested to any depth. A task with children is treated as a summary row and rendered differently from leaf tasks.

Adding dependencies

Set dependency on a task to the id of the task it depends on. ApexGantt draws an arrow between the tasks.

series: [
  { id: '1', name: 'Discovery',   startTime: '2024-04-01', endTime: '2024-04-07', progress: 100 },
  { id: '2', name: 'Design',      startTime: '2024-04-08', endTime: '2024-04-20', progress: 75,  dependency: '1' },
  { id: '3', name: 'Development', startTime: '2024-04-21', endTime: '2024-05-10', progress: 20,  dependency: '2' },
  { id: '4', name: 'Testing',     startTime: '2024-05-06', endTime: '2024-05-15', progress: 0,   dependency: '3' },
]

A task takes one dependency in its data. When it has more than one predecessor, add the others after render with addDependency. Here Testing also waits for Design:

gantt.render()
gantt.addDependency('2', '4')

An array in dependency is not read and draws no arrow. See Dependencies for dependency types and lag.

Customizing the date format

Dates are parsed with inputDateFormat, using dayjs tokens. The default is 'MM-DD-YYYY', which is why the examples on this page set 'YYYY-MM-DD' for their ISO dates. For day-first data:

const gantt = new ApexGantt(el, {
  inputDateFormat: 'DD/MM/YYYY',
  series: [...],
})

ISO dates under the default format still draw, because parsing falls back to a lenient read, but the edit dialog shows empty date fields and edited or dragged dates are written back as MM-DD-YYYY. Set the format to match your data.

For sub-day scheduling, add time tokens:

inputDateFormat: 'YYYY-MM-DD HH:mm'

With time tokens in the format and snapUnit set to 'hour' or 'minute', endTime is treated as an exclusive timestamp (the task ends at that exact moment, not at the end of that day).

Controlling what is visible

On first render ApexGantt fits the full data range into the timeline. Zoom with pixelsPerDay (pixels per day of timeline), and bring a task into view with scrollToTask:

const gantt = new ApexGantt(el, {
  series: [...],
  pixelsPerDay: 40,
})
gantt.render()
gantt.scrollToTask('4')

Next steps