diagram v1.1.6
A lightweight diagram editor built with vanilla HTML, CSS, and JavaScript. No dependencies, no build step. Create flowcharts and diagrams directly in the browser.
Features
- Shape Tools Rectangle, rounded rectangle, circle, diamond, triangle, terminator, and custom SVG shapes.
- Connections Draw lines and arrows between shapes with smart snapping and endpoint dragging.
- Custom SVG Paste your own SVG code to create custom shapes with full viewBox control.
- Text Labels Add floating text to shapes with adjustable font size, color, and alignment.
- Auto-Save Work is automatically saved to localStorage and survives page reloads.
- Touch Support Pointer Events for iPadOS and touchscreens, pinch-to-zoom, and finger-friendly handles.
- Keyboard Shortcuts Full keyboard navigation and editing shortcuts for power users.
Quick Start
Creating Shapes
Click a shape button in the toolbar, then click on the canvas to place it. Drag handles to resize, drag the body to move.
Drawing Connections
Select the Line tool (L), click and drag from one shape to another. Lines snap to shape edges automatically.
Adding Custom SVG Shapes
Click the Custom Shape button (last button in the toolbar), click on the canvas, then paste your SVG code into the Custom SVG textarea in the properties panel. Adjust the ViewBox Width and Height to match your SVG's coordinate space.
<svg> tag, the app defaults to a 100x100 coordinate space. Use the ViewBox fields to adjust if needed.
Native Custom SVGs
A custom SVG can be treated as a native shape (rect, circle, diamond, etc.) by checking Treat as native shape in the properties panel. This gives it the same fill color, stroke color, stroke width, and opacity controls as built-in shapes. To work correctly, the SVG must conform to the following rules.
Required Structure
The outer <svg> tag must include a viewBox attribute. This is the authoritative source of the shape's coordinate space and has no reliable automatic fallback.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 WIDTH HEIGHT"> <!-- inner content --> </svg>
<path d="...">. Always declare an explicit viewBox.
Content Rules
- No fill or stroke on content elements. Elements that should receive the user's selected fill and stroke must not declare
fill,stroke,fill-opacity, orstroke-opacitythemselves. The app injects these values automatically. - Author overrides are preserved. If an element declares its own
fillorstroke, that specific attribute is left untouched. The rest of the element (and all other elements) still receive the injected values. Use this for fixed details like divider lines or inner rings that should keep a specific color regardless of the user's panel settings. - Content must fit within viewBox bounds. Elements extending beyond the viewBox are clipped by
overflow="hidden"on the wrapper. - No nested
<svg>tags. Use<g>for grouping instead. - No
<text>elements. Text labels are handled separately by the app's built-in text control. <use>is not supported. There is no<defs>mechanism in the current content model; including<use>produces undefined rendering.
Supported Elements
| Element | Notes |
|---|---|
<rect> | x, y, width, height, rx, ry |
<circle> | cx, cy, r |
<ellipse> | cx, cy, rx, ry |
<polygon> | points |
<polyline> | points |
<path> | d, stroke-linecap, stroke-linejoin, stroke-dasharray |
<line> | x1, y1, x2, y2 |
<g> | transform for grouping; injection targets individual drawable children, not the wrapper |
Self-closing tags (<circle cx="50" cy="50" r="40"/>) are handled correctly.
Stroke Notes
Open paths and lines. Unlike closed shapes (rectangles, circles, polygons), open paths and lines have no "inset stroke" — the stroke expands equally on both sides of the centerline. If a line sits at the edge of the viewBox, its stroke may be clipped by overflow="hidden". Manually inset detail lines by at least half the expected stroke width from all edges.
Non-uniform scale. When Preserve SVG Aspect Ratio is unchecked, the SVG is stretched non-uniformly to fill the shape's width and height. This causes stroke width to appear thicker on the compressed axis and thinner on the stretched axis. Enable Preserve SVG Aspect Ratio for visually consistent stroke rendering.
Example: Star
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"> <polygon points="50,5 61,35 95,35 68,57 79,91 50,70 21,91 32,57 5,35 39,35"/> </svg>
A single polygon with no fill or stroke. The app injects the user's panel values. The star fills and strokes along its own outline — no bounding-box rectangle appears behind it.
Example: Gear with Fixed Detail
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<g>
<!-- Outer Gear Body (8 Teeth Path) -->
<path d="M 45,10 L 55,10 L 57,20 A 30,30 0 0,1 68,25 L 77,18 L 84,25 L 77,34 A 30,30 0 0,1 82,45 L 90,47 L 90,57 L 80,59 A 30,30 0 0,1 75,70 L 82,79 L 75,86 L 66,79 A 30,30 0 0,1 55,84 L 53,90 L 43,90 L 41,80 A 30,30 0 0,1 30,75 L 21,82 L 14,75 L 21,66 A 30,30 0 0,1 16,55 L 10,53 L 10,43 L 20,41 A 30,30 0 0,1 25,30 L 18,21 L 25,14 L 34,21 A 30,30 0 0,1 45,16 Z"/>
<!-- Fixed inner ring detail (Overrides panel fill/stroke) -->
<circle cx="50" cy="50" r="15" fill="none" stroke="#666" stroke-width="3"/>
</g>
</svg>
The gear body <path> has no fill/stroke and receives the user's panel values — the gear fills along its actual toothed outline, not a bounding-box rectangle. The inner ring declares its own fill="none" and stroke="#666", so that element keeps its fixed appearance regardless of the user's selected fill and stroke colors.
Example: Database Cylinder
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<g>
<!-- Main Cylinder Body (Receives panel fill & stroke colors) -->
<path d="M 15,25 A 35,15 0 0,0 85,25 L 85,75 A 35,15 0 0,1 15,75 Z M 15,25 A 35,15 0 0,1 85,25 A 35,15 0 0,1 15,25"/>
<!-- Internal Fixed Disk Dividers (Preserves gray stroke and no fill) -->
<path d="M 15,42 A 35,15 0 0,0 85,42" fill="none" stroke="#666" stroke-width="2"/>
<path d="M 15,58 A 35,15 0 0,0 85,58" fill="none" stroke="#666" stroke-width="2"/>
</g>
</svg>
The cylinder body <path> has no fill/stroke and receives the user's panel fill and stroke — the full cylinder paints with the selected colors. The two internal divider arcs declare fill="none" and their own stroke="#666", keeping them fixed regardless of the user's panel settings, just like real database diagram notation.
Keyboard Shortcuts
Technical Details
- Framework: Vanilla JavaScript (ES5-compatible), no dependencies
- Rendering: DOM-based shapes with inline SVG
- Input: Pointer Events API (unified mouse + touch + pen)
- State: Centralized state object with undo/redo (50 steps)
- Theme: Free Open Tools ecosystem dark/light scheme with toggle
- Canvas: 10,000 x 10,000 px grid layer
- Zoom: Mouse wheel zoom (0.1x to 5x) + pinch-to-zoom
Version History
- Connection z-height — selecting a line shows an editable Z field in the properties panel, matching shapes
- Unique z-heights guaranteed — every visible shape and connection is assigned a unique Z (dense ranks 0..N-1); two elements can never share a z-height
- Global stacking order — shapes and lines share one stack; a new line defaults just below the topmost shape it connects
- New shapes stack on top — newly created shapes appear above existing elements
- Anchors and hidden shapes excluded — internal anchor points and hidden shapes do not consume a z-height; a hidden shape rejoins the stack when shown
- Layers panel cleans up — internal anchor points are no longer listed
- Resize keeps position — resizing an off-grid shape (e.g. after a 1px nudge) no longer snaps or moves the anchored edge; only the dragged edge snaps to the grid
- Text padding on all four edges — the shape text padding setting now insets text from every edge, not just the aligned ones
- Snapped line ends follow the outline on resize — a line attached to a rounded corner or arc (terminator, roundRect) now stays on the outline when the shape is resized, instead of drifting off it
- Redo shortcut —
Ctrl/Cmd+Shift+Znow redoes, alongside the existingCtrl/Cmd+Y
- Treat as native shape — checkbox enables fill/stroke/opacity controls from properties panel
- Pan clamped to canvas bounds — edges always reachable; wheel/trackpad uses deferred clamping
- Triangle connection snap fixed — endpoints snap to true slanted edge, not bounding box bottom
- roundRect/terminator connection snap added — computes true distance to rounded visual outline
- Named ports project to true outline — connections land on actual visual edge for all shapes
- New-line preview no longer clips — dotted outline visible outside canvas container viewport
- Fixed undo on shape click — no spurious undo entries
- Arrow keys nudge shapes (1px; Shift+grid size), connections follow
- New-line port snapping with preview dots and outline highlight
- Fixed new-line preview jitter — start point pinned at click
- Lock Aspect Ratio — checkbox keeps width-to-height ratio during resize
- Preserve SVG Aspect Ratio — checkbox locks SVG to its natural ratio
- Right-click drag to pan canvas; context menu hides on pan start
- Refactored context menu hit-testing into shared function
- Added Shift+F10 / Menu key support for context menu
- 8 priority snap ports (corners + edge midpoints) with visual indicators
- Click connection lines even when overlapping shapes
- Independent fill and stroke opacity controls per shape
- Touch long-press (500ms) triggers context menu
- New Canvas button with confirmation before clearing
- Rounded rect fill fix — rx="8" matches stroke radius
- Connection snapping respects shape z-ordering
- Fixed two-finger pan using midpoint delta translation
- Panel resize handle — drag left edge (120–600px)
- Collapse button visible with accent styling
- Panel width saved/restored in localStorage
- Properties panel polished: section headers, hover/active states, 44px touch targets
- Pointer Events API — unified mouse, touch, and pen input
- Pinch-to-zoom on touchscreens
- Touch-friendly 22px resize handles
- Larger 40px+ toolbar and context menu targets
- Delete and Duplicate toolbar buttons
- "Edit Text" in context menu
- Versioning system and about page light theme
- Fixed connection endpoint snap on release
- Custom SVG shapes with viewBox control
- Export to PNG, JPG, PDF (auto-crop and full canvas)
- Save/Load project files (.json)
- Project name and canvas dimensions in properties panel
- Shape/connection naming and action log
- Text alignment and padding controls
- Connection endpoint dragging with smart snap
- Free Open Tools dark/light theme with toggle
- About page
- Shape tools: rect, rounded rect, circle, diamond, triangle, terminator
- Line/arrow connections with outline snapping
- Text tool for floating labels
- Fill, stroke, opacity, and text color styling
- Undo/redo (50-step history)
- Zoom and pan with mouse wheel
- Grid and snap-to-grid
- Context menu: duplicate, delete, reorder, lock
- Auto-save to localStorage
- Initial prototype — canvas, basic shapes, selection and dragging