Popular features/Grid sections
Loading live demo…from dhtmlxcode.com
Popular features
Grid sections
Split the chart into a task tree, the schedule, and a pinned KPI panel that share one scrollbar, with draggable splitters between the sections.
gantt.config.date_format = "%Y-%m-%d";
gantt.config.open_tree_initially = true;
gantt.config.order_branch = "marker";
gantt.config.row_height = 38;
gantt.config.bar_height = 22;
gantt.config.scale_height = 50;
gantt.config.scales = [
{ unit: "month", step: 1, format: "%F %Y" },
{ unit: "week", step: 1, format: function (d) { return gantt.date.date_to_str("%d %M")(d); } }
];
let AVATARS = {
logistics: { color: "#2563eb", initials: "LO" },
it: { color: "#16a34a", initials: "IT" },
ops: { color: "#d97706", initials: "OP" },
hr: { color: "#9333ea", initials: "HR" }
};
function money(n) { return "$" + Number(n).toLocaleString("en-US"); }
/* ---------------------------------------------------------------------------
* Row control: flag toggle, rendered in the pinned RIGHT grid
* (see rightSectionConfig below).
* ------------------------------------------------------------------------ */
let ICON = {
star: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"><path d="M8 2l1.8 3.9 4.2.5-3.1 2.9.8 4.2L8 11.8 4.3 13.4l.8-4.2L2 6.3l4.2-.5z"/></svg>',
starF:'<svg viewBox="0 0 16 16" fill="currentColor" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"><path d="M8 2l1.8 3.9 4.2.5-3.1 2.9.8 4.2L8 11.8 4.3 13.4l.8-4.2L2 6.3l4.2-.5z"/></svg>'
};
function flagCell(task) {
return '<span class="flag ' + (task.important ? "on" : "") + '" onclick="toggleFlag(event,' + task.id + ')">' +
(task.important ? ICON.starF : ICON.star) + "</span>";
}
function toggleFlag(e, id) {
e.stopPropagation();
let task = gantt.getTask(id);
task.important = !task.important;
gantt.updateTask(id);
}
gantt.templates.task_class = function (start, end, task) {
return task.important ? "is_important" : "";
};
gantt.config.columns = [
{ name: "text", label: "Task", tree: true, width: 240, resize: true },
{ name: "start_date", label: "Start", align: "center", width: 100, resize: true, template: function (task) {
return task.type === gantt.config.types.project ? "" : gantt.templates.date_grid(task.start_date, task);
}},
{ name: "duration", label: "Days", align: "center", width: 56, resize: true }
];
/* ---------------------------------------------------------------------------
* RIGHT SECTION: a second grid bound to the same task store; the flag
* toggle as the leading column, then owner / status / cost.
* ------------------------------------------------------------------------ */
let rightSectionConfig = {
columns: [
{ name: "flag", label: "", align: "center", width: 36, resize: true, template: flagCell },
{ name: "owner", label: "Owner", width: 110, resize: true, template: function (task) {
if (!task.team) return "";
let avatar = AVATARS[task.team];
return "<span class='gs_owner'><span class='gs_av' style='background:" + avatar.color + "'>" +
avatar.initials + "</span>" + task.owner + "</span>";
}},
{ name: "status", label: "Status", align: "center", width: 96, resize: true, template: function (task) {
if (task.type === gantt.config.types.project || !task.status) return "";
let map = { track: "On track", risk: "At risk", late: "Late", done: "Done" };
return "<span class='gs_status " + task.status + "'>" + map[task.status] + "</span>";
}},
{ name: "cost", label: "Budget", align: "right", width: 92, resize: true, template: function (task) {
return task.cost ? "<span class='gs_cost'>" + money(task.cost) + "</span>" : "";
}}
]
};
/* ---------------------------------------------------------------------------
* LAYOUT: grid | timeline | pinned grid, one shared vertical scrollbar
* ------------------------------------------------------------------------ */
gantt.config.layout = {
css: "gantt_container",
rows: [
{ cols: [
{ view: "grid", width: 420, scrollY: "scrollVer" },
{ resizer: true, width: 1, group: "vertical", id: "r1" },
{ view: "timeline", id: "timeline", scrollX: "scrollHor", scrollY: "scrollVer" },
{ resizer: true, width: 1, group: "vertical", id: "r2" },
{ view: "grid", id: "rightGrid", bind: "task", width: 334,
config: rightSectionConfig, scrollY: "scrollVer", css: "pinned_grid" },
{ view: "scrollbar", id: "scrollVer", group: "vertical" }
]},
{ view: "scrollbar", id: "scrollHor" }
]
};
/* ---------------------------------------------------------------------------
* DATA
* ------------------------------------------------------------------------ */
let demoData = {
tasks: [
{ id: 1, text: "Warehouse rollout", type: "project", open: true, owner: "Program", team: "ops", status: "track" },
{ id: 10, text: "Site & facilities", type: "project", parent: 1, open: true, owner: "Ops", team: "ops", status: "risk" },
{ id: 11, text: "Lease & permits", parent: 10, start_date: "2026-04-06", duration: 10, progress: 1, owner: "M. Ortiz", team: "ops", status: "done", cost: 42000 },
{ id: 12, text: "Racking install", parent: 10, start_date: "2026-04-20", duration: 14, progress: 0.5, owner: "M. Ortiz", team: "ops", status: "risk", cost: 88000 },
{ id: 13, text: "Power upgrade", parent: 10, start_date: "2026-04-28", duration: 8, progress: 0.3, owner: "M. Ortiz", team: "ops", status: "risk", cost: 64000 },
{ id: 14, text: "Safety inspection", parent: 10, start_date: "2026-05-11", duration: 4, progress: 0, owner: "M. Ortiz", team: "ops", status: "track", cost: 12000 },
{ id: 15, text: "Dock door retrofit", parent: 10, start_date: "2026-05-15", duration: 9, progress: 0.2, owner: "M. Ortiz", team: "ops", status: "risk", cost: 37000 },
{ id: 16, text: "Signage & striping", parent: 10, start_date: "2026-05-26", duration: 5, progress: 0, owner: "M. Ortiz", team: "ops", status: "track", cost: 8500 },
{ id: 20, text: "IT & systems", type: "project", parent: 1, open: true, owner: "IT", team: "it", status: "track", important: true },
{ id: 21, text: "Network & WiFi", parent: 20, start_date: "2026-04-27", duration: 8, progress: 0.6, owner: "S. Patel", team: "it", status: "track", cost: 31000 },
{ id: 22, text: "WMS deployment", parent: 20, start_date: "2026-05-07", duration: 16, progress: 0.3, owner: "S. Patel", team: "it", status: "track", cost: 120000, important: true },
{ id: 23, text: "Scanner rollout", parent: 20, start_date: "2026-05-25", duration: 6, progress: 0, owner: "S. Patel", team: "it", status: "track", cost: 24000 },
{ id: 24, text: "Label printer setup", parent: 20, start_date: "2026-05-27", duration: 5, progress: 0, owner: "S. Patel", team: "it", status: "track", cost: 16000 },
{ id: 25, text: "ERP integration", parent: 20, start_date: "2026-06-01", duration: 10, progress: 0, owner: "S. Patel", team: "it", status: "risk", cost: 72000 },
{ id: 26, text: "Access control setup", parent: 20, start_date: "2026-06-03", duration: 6, progress: 0, owner: "S. Patel", team: "it", status: "track", cost: 19500 },
{ id: 30, text: "Logistics", type: "project", parent: 1, open: true, owner: "Logistics", team: "logistics", status: "late" },
{ id: 31, text: "Carrier contracts", parent: 30, start_date: "2026-05-04", duration: 9, progress: 0.4, owner: "J. Lee", team: "logistics", status: "late", cost: 18000 },
{ id: 32, text: "Inbound test run", parent: 30, start_date: "2026-05-18", duration: 7, progress: 0, owner: "J. Lee", team: "logistics", status: "track", cost: 9000 },
{ id: 33, text: "Outbound simulation", parent: 30, start_date: "2026-05-28", duration: 6, progress: 0, owner: "J. Lee", team: "logistics", status: "track", cost: 11000 },
{ id: 34, text: "Peak-volume rehearsal", parent: 30, start_date: "2026-06-08", duration: 5, progress: 0, owner: "J. Lee", team: "logistics", status: "track", cost: 14000 },
{ id: 35, text: "Returns process pilot", parent: 30, start_date: "2026-06-09", duration: 4, progress: 0, owner: "J. Lee", team: "logistics", status: "late", cost: 7200 },
{ id: 40, text: "People", type: "project", parent: 1, open: true, owner: "HR", team: "hr", status: "track" },
{ id: 41, text: "Hiring & training", parent: 40, start_date: "2026-05-11", duration: 12, progress: 0.2, owner: "R. Kim", team: "hr", status: "track", cost: 56000 },
{ id: 42, text: "Shift scheduling", parent: 40, start_date: "2026-05-25", duration: 7, progress: 0, owner: "R. Kim", team: "hr", status: "track", cost: 18000 },
{ id: 43, text: "Safety certification", parent: 40, start_date: "2026-06-02", duration: 6, progress: 0, owner: "R. Kim", team: "hr", status: "risk", cost: 15500 }
],
links: [
{ id: 1, source: 11, target: 12, type: "0" },
{ id: 2, source: 11, target: 13, type: "0" },
{ id: 3, source: 12, target: 14, type: "0" },
{ id: 4, source: 13, target: 14, type: "0" },
{ id: 18, source: 14, target: 15, type: "0" },
{ id: 19, source: 15, target: 16, type: "0" },
{ id: 5, source: 21, target: 22, type: "0" },
{ id: 6, source: 22, target: 23, type: "0" },
{ id: 7, source: 22, target: 24, type: "0" },
{ id: 8, source: 23, target: 25, type: "0" },
{ id: 9, source: 24, target: 25, type: "0" },
{ id: 20, source: 25, target: 26, type: "0" },
{ id: 10, source: 31, target: 32, type: "0" },
{ id: 11, source: 32, target: 33, type: "0" },
{ id: 12, source: 33, target: 34, type: "0" },
{ id: 21, source: 34, target: 35, type: "0" },
{ id: 13, source: 41, target: 42, type: "0" },
{ id: 22, source: 42, target: 43, type: "0" },
{ id: 14, source: 12, target: 41, type: "0" },
{ id: 15, source: 14, target: 32, type: "0" },
{ id: 16, source: 22, target: 42, type: "0" },
{ id: 17, source: 23, target: 34, type: "0" }
]
};
/* ---------------------------------------------------------------------------
* ZOOM
* ------------------------------------------------------------------------ */
gantt.ext.zoom.init({
levels: [
{ name: "week", scale_height: 50, scales: [{ unit: "month", step: 1, format: "%F %Y" }, { unit: "week", step: 1, format: function (d) { return gantt.date.date_to_str("%d %M")(d); } }] },
{ name: "month", scale_height: 50, scales: [{ unit: "year", step: 1, format: "%Y" }, { unit: "month", step: 1, format: "%M" }] }
],
element: function () { return gantt.$root.querySelector(".gantt_task"); }
});
DHX.zoom.init(gantt, ["week", "month"], "zoom_seg", "footer_scale");
function setZoom(name) { DHX.zoom.set(name); }
/* ---------------------------------------------------------------------------
* INIT
* ------------------------------------------------------------------------ */
gantt.init("gantt_here");
gantt.parse(demoData);
DHX.zoom.set("week");<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Grid sections: dhtmlxGantt</title>
<script src="../../codebase/dhtmlxgantt.js?v=10.0.0"></script>
<link rel="stylesheet" href="../../codebase/dhtmlxgantt.css?v=10.0.0">
<link rel="stylesheet" href="../common/demo-controls/dhx_controls.css">
<script src="../common/demo-controls/dhx_controls.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
<style>
body { display: flex; flex-direction: column; }
#gantt_here { width: 100%; flex: 1 1 auto; min-height: 0; }
.footer_note { white-space: nowrap; }
@media (max-width: 820px) {
.footer_note { display: none; }
}
.gantt_layout_cell.pinned_grid { box-shadow: inset 1px 0 0 var(--dhx-line); }
.gs_owner { display: inline-flex; align-items: center; gap: 7px; }
.gs_av {
width: 22px; height: 22px; border-radius: 50%; flex: none;
color: #fff; font: 600 10px var(--dhx-font);
display: inline-flex; align-items: center; justify-content: center;
}
.gs_status {
display: inline-block; padding: 1px 9px; border-radius: 10px;
font: 600 11px var(--dhx-font);
}
.gs_status.track { background: var(--dhx-ok-bg); color: var(--dhx-ok-ink); }
.gs_status.risk { background: var(--dhx-warn-bg); color: var(--dhx-warn-ink); }
.gs_status.late { background: var(--dhx-danger-bg); color: var(--dhx-danger-ink); }
.gs_status.done { background: var(--dhx-neutral-bg); color: var(--dhx-neutral-ink); }
.gs_cost { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--dhx-ink); }
.gantt_grid_head_cell { font-weight: 600; }
.flag { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; vertical-align: middle; cursor: pointer; color: var(--dhx-muted); }
.flag:hover { color: #f59e0b; }
.flag.on { color: #f59e0b; }
.flag svg { width: 15px; height: 15px; }
.gantt_task_line.is_important { box-shadow: 0 0 0 2px #f59e0b, 0 1px 2px rgba(16,24,40,.18); }
</style>
</head>
<body>
<div class="dhx_header dhx_header--centered">
<div class="dhx_seg" id="zoom_seg">
<button class="dhx_btn" data-zoom="week" onclick="setZoom('week')">Week</button>
<button class="dhx_btn" data-zoom="month" onclick="setZoom('month')">Month</button>
</div>
</div>
<div id="gantt_here"></div>
<div class="dhx_footer">
<span class="footer_note">Drag the splitters to resize sections. The pinned right panel stays row-aligned with the tree and the schedule.</span>
<div class="dhx_footer__right"><span id="footer_scale">Week scale</span></div>
</div>
</body>
</html>