Skip to main content

Visualizing critical path and slack

The functionality is available in PRO Edition only

PRO

Visualizing critical path

The critical path is the sequence of tasks that defines the minimum project duration. Delaying any task on this path delays the entire project.

Enabling critical path

Use the criticalPath property to enable built-in Critical Path Method (CPM) analysis:

<script>
import { Gantt } from "@svar-ui/svelte-gantt";
import { getData } from "./data";

const { tasks, links, scales } = getData();
</script>

<Gantt {tasks} {links} {scales} criticalPath={{ type: "flexible" }} />

When enabled, critical tasks and links receive a critical boolean property (task.critical and link.critical) set to true for elements that belong to the critical path.

If there are multiple parallel paths with the same duration, the chart highlights the first valid path.

Calculation modes

The criticalPath property accepts an object with the required type field:

criticalPath?: {
type: "strict" | "flexible";
};

The following Gantt props influence strict critical path calculations:

Example with mode switching:

<script>
import { Gantt } from "@svar/svelte-gantt";
import { getData } from "./data";

const data = getData("critical");

let api = $state();
let mode = "flexible";
let projectStart = new Date(2024, 3, 2);
let projectEnd = new Date(2024, 3, 12);
</script>

<Gantt
tasks={data.tasks}
links={data.links}
scales={data.scales}
criticalPath={{ type: mode }}
{projectStart}
{projectEnd}
/>

Visualizing slack values

Slack (float) shows how much a task can be delayed without affecting successors or the overall project end date. When enabled, slack is calculated automatically.

Enabling slack calculation

To enable slack, use the slack property:

<script>
import { Gantt } from "@svar-ui/svelte-gantt";
import { getData } from "./data";

const { tasks, links, scales } = getData();
</script>

<Gantt {tasks} {links} {scales} slack />

Once enabled, the Gantt calculates slack for each task and attaches an object to it:

slack?: {
earliestStart: Date; // Earliest date the task can start (forward pass result)
latestStart: Date; // Latest date the task can start without delaying the project
totalSlack: number; // Days the task can be delayed without affecting the project end (0 = critical)
freeSlack: number; // Days the task can be delayed without affecting any successor
}

Note: Slack values are calculated in working days when a calendar is applied.

Displaying slack in grid columns

You can add custom columns to the grid to visualize slack values. Use the built-in slack column ID to access the slack object directly via the template function, or use getter of the columns property to extract a specific field:

<script>
import { Gantt } from "@svar-ui/svelte-gantt";
import { getData } from "./data";

const { tasks, links, scales } = getData();

const columns = [
{ id: "text", header: "Task name", flexgrow: 1 },
{
id: "earliestStart",
header: "Earliest start",
align: "center",
width: 120,
getter: t => t.slack.earliestStart,
template: v => (v ? v.toLocaleDateString() : "-"),
},
{
id: "latestStart",
header: "Latest start",
align: "center",
width: 120,
getter: t => t.slack.latestStart,
template: v => (v ? v.toLocaleDateString() : "-"),
},
{
id: "freeSlack",
header: "Free slack",
align: "center",
width: 100,
getter: t => t.slack.freeSlack,
template: v => v ?? "-",
},
{
id: "totalSlack",
header: "Total slack",
align: "center",
width: 100,
getter: t => t.slack.totalSlack,
},
];
</script>

<Gantt {tasks} {links} {scales} {columns} slack />
note

If a column displays a derived or nested value (for example, task.slack.totalSlack), use getter to extract the value. The returned value is used for sorting and is passed to the template function as its first argument.

Total slack is also visualized directly on task bars for normal scheduled tasks (not milestones or summary tasks).

Slack with unscheduled tasks

When unscheduledTasks is enabled, slack values are not applicable to unscheduled tasks. You can handle this via the column template:

<script>
import { Gantt } from "@svar-ui/svelte-gantt";
import { getData } from "./data";

const { tasks, links, scales } = getData();

const columns = [
{
id: "freeSlack",
header: "Free slack",
align: "center",
width: 100,
getter: t => t.slack?.freeSlack,
template: v => v ?? "-"
},
{
id: "totalSlack",
header: "Total slack",
align: "center",
width: 100,
getter: t => t.slack?.totalSlack,
template: v => v ?? "-"
}
];
</script>

<Gantt {tasks} {links} {scales} {columns} slack unscheduledTasks />

Accessing critical tasks and slack data

Once critical path or slack is calculated, you can get the corresponding data via the API (api.getState(), api.getTask(), api.serialize()).

Critical path:

// Check if a specific task is on the critical path
const isCritical = api.getTask(id).critical;

// Iterate over all tasks to find critical ones
api.getState().tasks.forEach(task => {
console.log(task.id, task.critical);
});

// Or via serialized data
api.serialize().forEach(task => {
console.log(task.id, task.critical);
});

// Check critical links
api.getState().links.forEach(link => {
console.log(link.id, link.critical);
});

Slack:

// Access slack for a specific task
const freeSlack = api.getTask(id).slack.freeSlack;

// Iterate over all tasks
api.getState().tasks.forEach(task => {
console.log(task.slack?.totalSlack);
});

// Or via serialized data
api.serialize().forEach(task => {
console.log(task.slack?.freeSlack);
});

Related samples:

Related articles: