Visual Timeline · Export PNG · 100% Free
Gantt Chart Generator
Build professional project timelines instantly, no signup and no download. Add tasks, set dates, assign colours and export your Gantt chart as a PNG. Works smoothly on mobile too. Pro Mode unlocks milestones, dependencies, progress tracking, team assignment and critical path.
100% Private — saved only in your browser, never sent to a server
● Pro Version is Free for now
✓ Milestones · Dependencies · Progress · Team ·
Critical Path · Today Line · Zoom · CSV/PDF/Word Export unlocked
Critical Path · Today Line · Zoom · CSV/PDF/Word Export unlocked
Day
Night
Total Tasks
0
in chart
Duration
0
total days
Avg Progress PRO
0%
completion
End Date
—
project finish
Project:
Zoom PRO
You can also type the date directly (YYYY-MM-DD)
Gantt Chart
Critical Path Highlighted
Add your first task above to start building your Gantt chart
Save chart as:
Task List
0 tasks
No tasks yet. Add a task above.
📖 Quick Reference
▬Bars show each task's start date and duration.
◆Milestones mark key single-day dates on the timeline.
→Dependencies arrows show which tasks must finish first.
🔴Critical path the chain of tasks that decides your finish date.
🔴 Critical Path PRO
The critical path is auto-highlighted in red on your chart, the longest chain of dependent tasks that determines your project's earliest finish date.
💡 Project Planning Tips PRO
Scroll for more options
' + esc(t.assignee) + '' : ''; const milestoneStr = t.type === 'milestone' ? ' ◆' : ''; const rowBg = idx % 2 === 0 ? '#fff' : '#f8fafc'; let cells = '
${esc(proj)}
Generated by SmallStudyTools.com | ${new Date().toLocaleDateString()}
smallstudytools.com — Free Online Gantt Chart Generator
`;const blob = new Blob([html], {type: 'text/html;charset=utf-8'}); const a = document.createElement('a'); a.download = 'smallstudytools-gantt.doc'; a.href = URL.createObjectURL(blob); a.click(); toast('Word file downloaded! Open with Microsoft Word or LibreOffice.'); }function exportCSV() { if (!tasks.length) { toast('Add tasks first'); return; } const headers = ['#','Task Name','Start Date','Duration (days)','End Date','Progress %','Assignee','Type','Depends On']; const rows = tasks.map((t,i) => [ i+1, t.name, t.start, t.dur, fmtDate(addDays(parseDate(t.start), t.dur)), t.progress||0, t.assignee||'', t.type||'task', t.dependsOn||'' ]); const csv = [headers, ...rows].map(r => r.map(v => `"${String(v).replace(/"/g,'""')}"`).join(',')).join('\n'); const blob = new Blob([csv], {type:'text/csv'}); const a = document.createElement('a'); a.download = 'smallstudytools-gantt.csv'; a.href = URL.createObjectURL(blob); a.click(); toast('CSV exported!'); }// ── ZOOM (PRO) ───────────────────────────────────────────────── function setZoom(z, btn) { zoom = z; document.querySelectorAll('.zoom-btn').forEach(b => b.classList.remove('active')); btn.classList.add('active'); redraw(); }// ── SAMPLE DATA ──────────────────────────────────────────────── function loadSample() { const today = new Date(); const base = fmtDate(today); const d = (n) => fmtDate(addDays(today, n)); try { document.getElementById('fStart')._flatpickr && document.getElementById('fStart')._flatpickr.setDate(today); } catch(e) {} tasks = [ {id:1,name:'Research & Planning',start:base,dur:5,color:'#4f46e5',progress:100,assignee:'Alice',type:'task',dependsOn:null}, {id:2,name:'Design Phase',start:d(5),dur:7,color:'#7c3aed',progress:60,assignee:'Bob',type:'task',dependsOn:1}, {id:3,name:'Development',start:d(10),dur:14,color:'#10b981',progress:30,assignee:'Alice',type:'task',dependsOn:2}, {id:4,name:'Testing',start:d(22),dur:5,color:'#f59e0b',progress:0,assignee:'Carol',type:'task',dependsOn:3}, {id:5,name:'Launch',start:d(27),dur:1,color:'#ef4444',progress:0,assignee:'',type:'milestone',dependsOn:4}, ]; save(); redraw(); renderTaskList(); toast('✓ Sample loaded — 5 tasks added! Try switching to Pro for milestones, progress & more.'); }// ── ACTIONS ──────────────────────────────────────────────────── function clearAll() { if (!tasks.length) return; tasks = []; save(); redraw(); renderTaskList(); toast('Cleared!'); }// ── MODE ─────────────────────────────────────────────────────── function setMode(mode) { isPro = mode === 'pro'; document.getElementById('btnSimple').classList.toggle('active', !isPro); document.getElementById('btnPro').classList.toggle('active', isPro); widget().classList.toggle('pro-mode', isPro); document.getElementById('proModeBar').style.display = isPro ? 'flex' : 'none'; document.getElementById('modeHint').textContent = isPro ? 'Milestones · Dependencies · Progress · Team · Critical Path · Today Line · Zoom · CSV Export' : 'Add tasks · set dates · export PNG'; document.getElementById('formGrid').className = isPro ? 'form-grid-pro' : 'form-grid'; redraw(); renderTaskList(); try { localStorage.setItem('sst_gantt_mode', mode); } catch(e) {} }// ── UTILS ────────────────────────────────────────────────────── function esc(s) { return (s||'').replace(/&/g,'&').replace(//g,'>'); } function save() { try { localStorage.setItem(SK, JSON.stringify(tasks)); } catch(e) {} } function toast(msg) { const t=document.getElementById('toast'); t.textContent=msg; t.classList.add('show'); setTimeout(()=>t.classList.remove('show'), 2200); }// ── INIT ─────────────────────────────────────────────────────── try { if (typeof flatpickr === 'function') { flatpickr('#fStart', { dateFormat: 'Y-m-d', altInput: true, altFormat: 'd M Y', defaultDate: new Date(), disableMobile: true, allowInput: true, }); } else { document.getElementById('dateFallbackNote').classList.add('show'); } } catch (e) { document.getElementById('dateFallbackNote').classList.add('show'); }try { const saved = JSON.parse(localStorage.getItem(SK) || '[]'); if (Array.isArray(saved) && saved.length) { tasks = saved; redraw(); renderTaskList(); } const savedMode = localStorage.getItem('sst_gantt_mode'); if (savedMode === 'pro') setMode('pro'); } catch(e) {}