Why Not SVG?
SVG is literally called Scalable Vector Graphics. It's a vector format. It lives in browsers. It scales infinitely.
Why wouldn't we use it for a vector editor?
The Appeal
Declarative. Describe what you want, not how to draw it:
<rect x="10" y="10" width="100" height="50" fill="red"/>
DOM integration. SVG elements are DOM nodes. Event handlers, CSS styling, accessibility—all work.
Inspect with DevTools. See every shape in the Elements panel. Debug visually.
Built-in animation. SMIL animations, CSS transitions, all free.
Native browser rendering. The browser handles rasterization. You handle shapes.
For icons, illustrations, and simple graphics, SVG is excellent.
The DOM Problem
Each SVG element is a DOM node. DOM nodes are expensive.
<svg>
<rect id="rect1" .../>
<rect id="rect2" .../>
<!-- 5000 more rectangles -->
</svg>
5000 rectangles = 5000 DOM nodes = browser struggling.
Measure it:
| Objects | SVG Render | Canvas Render |
|---|---|---|
| 100 | 2ms | 0.5ms |
| 1000 | 25ms | 3ms |
| 5000 | 150ms | 12ms |
| 10000 | 400ms+ | 25ms |
At 10,000 objects, SVG drops below 3fps. Canvas stays smooth.
Update Overhead
Change a shape? Update the DOM.
element.setAttribute('x', newX);
element.setAttribute('y', newY);
element.setAttribute('width', newWidth);
// Triggers reflow, repaint
Every attribute change can trigger layout recalculation. Batch updates help, but DOM mutation is inherently slow.
Canvas: modify data, call draw(). No intermediate DOM layer.
Styling Limitations
SVG has fills and strokes. But:
No per-segment dashing:
<!-- This path has one dash pattern for all segments -->
<path d="M0,0 L100,100 L200,0" stroke-dasharray="5,5"/>
Limited blend modes: SVG filter and feBlend exist, but:
- Complex filter chains are slow
- Not all blend modes available
- Filter regions require careful management
No stroke alignment: SVG strokes are always centered. Inside/outside stroke? Build it yourself with duplicate paths.
Text Nightmare
SVG text is deceptively complex:
<text x="100" y="100">Hello</text>
Looks simple. Then:
- Font loading: Fonts must load before measurement works
- Line breaking: Manual. SVG doesn't wrap text.
- Rich text: Multiple
<tspan>elements, manually positioned - Vertical text:
writing-modesupport varies - Text on path: Works, but layout is tricky
Canvas2D has measureText(). Skia has full text shaping. SVG requires building a text engine.
Transform Inheritance
SVG transforms cascade through the DOM:
<g transform="translate(100, 100)">
<g transform="rotate(45)">
<rect x="0" y="0" width="50" height="50"/>
</g>
</g>
Convenient for simple cases. Problem:
Reading back world coordinates requires walking the DOM tree, accumulating transforms. The browser does this automatically for rendering, but you can't easily access intermediate results.
Modifying child positions while respecting parent transforms is matrix math you have to do yourself anyway.
Z-Order Rigidity
SVG renders in document order. Back-to-front.
<svg>
<rect id="background"/>
<rect id="foreground"/> <!-- Always on top -->
</svg>
Reorder z-index? Move DOM nodes.
foreground.parentNode.insertBefore(foreground, background);
DOM reordering triggers reflow. In Canvas, z-order is just array indices.
Filter Performance
SVG filters are powerful:
<filter id="blur">
<feGaussianBlur stdDeviation="5"/>
</filter>
<rect filter="url(#blur)"/>
But:
- Each filter creates off-screen buffers
- Complex filter chains multiply buffers
- Filter region management is manual
- Performance degrades non-linearly with complexity
Same operations in WebGL: one draw call with shader.
When SVG Makes Sense
Static illustrations. Icons, logos, diagrams. Load, display, done.
Simple interactivity. Hover effects, click handlers on shapes. Few elements.
CSS-driven animation. Transitions and keyframe animations on a handful of elements.
Accessibility requirements. SVG elements can have ARIA attributes. Screen readers understand the structure.
SEO needs. Text in SVG is indexable. Canvas content isn't.
The Hybrid Approach
Some editors use SVG for UI, Canvas for content:
<div class="editor">
<canvas id="content"/> <!-- Thousands of shapes -->
<svg id="ui"> <!-- Selection box, handles -->
<rect class="selection"/>
<circle class="handle"/>
</svg>
</div>
SVG overlays handle UI elements (few objects, needs events). Canvas handles content (many objects, needs performance).
We considered this. Complexity wasn't worth it. All Canvas/Skia is simpler.
Summary
SVG's DOM model is both its strength and weakness:
Strength: Integration with web platform, CSS, events, accessibility.
Weakness: Performance ceiling at scale, update overhead, limited styling control.
For a vector editor with thousands of objects, complex effects, and 60fps interaction:
SVG won't get you there.
It's not the rendering engine. It's the architecture. DOM nodes are the wrong abstraction for graphics-intensive applications.
Next: Why Not Raw WebGL? →