Theming and Customization
ApexGantt ships with built-in light and dark themes. Every color token is individually overridable, bar labels support custom HTML renderers, and the entire timeline can be mirrored for right-to-left languages.
Built-in themes
The theme option accepts 'light' (default) or 'dark'. The dark preset adjusts bar colors, backgrounds, and borders to suit dark surfaces without requiring any manual color overrides.
// Initialize with dark theme
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
theme: 'dark'
})
You can switch the theme at runtime using update(). The chart re-renders immediately with no page reload required.
// Toggle between themes
document.querySelector('#toggle-theme').addEventListener('click', () => {
const current = gantt.options.theme
gantt.update({ theme: current === 'dark' ? 'light' : 'dark' })
})
Color customization
All color options are optional. Unset options fall back to the theme default (light or dark). Override only the tokens you need.
| Option | Light default | Dark default | What it controls |
|---|---|---|---|
backgroundColor | #FFFFFF | (dark surface) | Chart container background |
barBackgroundColor | #87B7FE | #818CF8 | Default task bar fill |
barTextColor | #FFFFFF | #FFFFFF | Text rendered inside task bars |
summaryBarColor | #B9CECE | #B9CECE | Summary/parent row bar color |
milestoneColor | #7C3AED | #7C3AED | Milestone diamond color |
criticalBarColor | #e53935 | #e53935 | Task bar on the critical path |
arrowColor | #94A3B8 | #94A3B8 | Dependency arrow lines |
criticalArrowColor | #e53935 | #e53935 | Dependency arrows on the critical path |
borderColor | #eff0f0 | (dark border) | Row and cell divider lines |
cellBorderColor | #D0D7DE | (dark border) | Task table cell borders |
headerBackground | #EBF3FB | (dark header) | Timeline header background |
The following example applies a neutral, low-contrast palette suited to a dashboard that uses muted grays:
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
theme: 'light',
backgroundColor: '#F9FAFB',
headerBackground: '#F3F4F6',
barBackgroundColor: '#6366F1',
barTextColor: '#FFFFFF',
summaryBarColor: '#A1A1AA',
milestoneColor: '#8B5CF6',
criticalBarColor: '#EF4444',
arrowColor: '#CBD5E1',
borderColor: '#E5E7EB',
cellBorderColor: '#E5E7EB'
})
Per-task colors
Task bar color
Set barBackgroundColor directly on a task object inside series to override the global bar color for that specific task. This is useful for encoding priority, status, or ownership without a separate legend.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: [
{
id: 'design',
name: 'Design',
startTime: '2024-03-01',
endTime: '2024-03-10'
// Uses global barBackgroundColor
},
{
id: 'urgent',
name: 'Critical Fix',
startTime: '2024-03-04',
endTime: '2024-03-06',
barBackgroundColor: '#FF4560' // Red bar for this task only
},
{
id: 'review',
name: 'Review',
startTime: '2024-03-08',
endTime: '2024-03-12',
barBackgroundColor: '#00E396' // Green bar to signal approved
}
]
})
Row background color
Set rowBackgroundColor on a task to highlight its entire row. This is separate from rowBackgroundColors (the alternating pattern) and takes precedence over it.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: [
{
id: 'phase-1',
name: 'Phase 1',
startTime: '2024-03-01',
endTime: '2024-03-31',
rowBackgroundColor: '#EEF2FF' // Indigo tint for the entire row
},
{
id: 'task-1a',
name: 'Task 1A',
startTime: '2024-03-01',
endTime: '2024-03-10',
parentId: 'phase-1'
},
{
id: 'phase-2',
name: 'Phase 2',
startTime: '2024-04-01',
endTime: '2024-04-30',
rowBackgroundColor: '#F0FDF4' // Green tint for Phase 2
}
]
})
Row alternating background
rowBackgroundColors accepts an array of color strings that cycle across rows from top to bottom. The default is a single-color array (['#FFFFFF']), which produces a uniform background. Passing two colors produces a classic zebra stripe.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
rowBackgroundColors: ['#FFFFFF', '#F8F9FA']
})
You can pass more than two colors. The pattern repeats from the beginning once all colors are used:
rowBackgroundColors: ['#FFFFFF', '#F5F3FF', '#F0FDF4']
// Row 1 = white, Row 2 = lavender, Row 3 = green, Row 4 = white again, ...
Note that a per-task rowBackgroundColor overrides the alternating pattern for that specific row.
Bar label position and content
Position
The barLabel.position option controls where the label appears relative to the task bar. The four accepted values are:
'inside': label renders inside the bar. The bar must be wide enough to display it.'left': label renders to the left of the bar.'right'(default): label renders to the right of the bar.'auto': the chart picks'inside'when the bar is wide enough, and'right'otherwise.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
barLabel: {
position: 'auto',
field: 'name'
}
})
Field
barLabel.field sets which property from the task object is used as the label text. The default is 'name'. You can point it at any property present on your task objects, for example 'assignee' or 'progress'.
barLabel: {
position: 'right',
field: 'name'
}
Custom render function
For full control over what appears in the label, supply a render function. It receives the resolved task object and must return an HTML string, an HTMLElement, or null/undefined (which falls back to the field value).
This approach lets you inject icons, progress indicators, or any markup into the label without modifying task data.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
barLabel: {
position: 'right',
render: (task) => {
if (task.progress == null) return null
const color = task.progress >= 100 ? '#10B981' : '#6366F1'
return `<span style="display:flex;gap:6px;align-items:center;font-size:12px">
<strong>${task.name}</strong>
<span style="color:${color};opacity:0.85">${task.progress}%</span>
</span>`
}
}
})
Return null or undefined from render to let the chart fall back to the field value. This makes conditional rendering straightforward: enhance milestone tasks with an icon but leave regular tasks as plain text.
Typography
The following options control the font used across the entire chart (bars, headers, the task table, and tooltips). They accept any valid CSS value.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
fontFamily: 'Inter, sans-serif',
fontSize: '13px',
fontWeight: '400',
fontColor: '#374151'
})
| Option | Default | Description |
|---|---|---|
fontFamily | system font | Font stack for all chart text |
fontSize | '13px' | Base font size |
fontWeight | '400' | Base font weight |
fontColor | '#374151' | Default text color (task table, headers) |
Bar text color is controlled separately by barTextColor.
Row height and bar border radius
Row height
rowHeight sets the height of each task row in pixels. The default is 38. Increasing it gives more breathing room between bars, which helps when bars carry labels or progress indicators.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
rowHeight: 48
})
Bar border radius
barBorderRadius accepts any CSS border-radius value. The default is '5px'. Set it to '0' for sharp rectangular bars or '12px' for a pill-like appearance.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
barBorderRadius: '8px'
})
RTL support
Setting locale.direction to 'rtl' mirrors the entire timeline axis so dates progress from right to left. The task table moves to the right side of the chart. This is intended for Arabic, Hebrew, and Persian project plans where right-to-left reading order is expected.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
locale: {
direction: 'rtl'
}
})
The default is 'ltr'. Switching direction at runtime with update() is supported:
gantt.update({ locale: { direction: 'rtl' } })
Custom CSS injection
canvasStyle accepts a raw CSS string that is applied directly to the root chart container element. Use it for overrides that have no dedicated option: custom scrollbar styling, pointer cursors on hover, or additional box-shadow effects.
const gantt = new ApexGantt(document.querySelector('#chart'), {
series: tasks,
canvasStyle: `
border: 1px solid #E5E7EB;
border-radius: 8px;
box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1);
font-feature-settings: 'tnum';
`
})
A common use case is customizing the scrollbar in Chromium-based browsers so it blends with your chart's color scheme:
canvasStyle: `
border: 1px solid #CACED0;
box-sizing: border-box;
scrollbar-width: thin;
scrollbar-color: #CBD5E1 transparent;
`
Because canvasStyle is a raw string injection, it bypasses the options type system. Prefer dedicated options (like backgroundColor or borderColor) when they cover your use case, and fall back to canvasStyle only for properties that have no dedicated option.