Restyle the controls with CSS
Selection boxes and handles are real elements carrying documented class names and data attributes. Change how they look without forking anything.
Styling guide
A canvas editor engine for design tools, whiteboards, diagram editors and annotation UIs. Shapes render to canvas; selection UI is DOM you style with CSS. MIT licensed, no watermark, no framework required.
Konva and Fabric draw selection handles into the canvas alongside the artwork. Two consequences follow, and neither can be worked around from application code: the handles cannot be restyled with CSS, and assistive technology cannot see them at all.
HeadlessCanvas splits the two layers:
┌─────────────────────────────────────┐
│ DOM overlay — selection, handles │ ← your CSS, your markup, keyboard accessible
├─────────────────────────────────────┤
│ Canvas — shapes, images │ ← fast rendering, no UI drawn here
└─────────────────────────────────────┘tldraw shares this architecture but is not open source: production use requires a licence key, the watermark must stay unless you buy a commercial licence, and every downstream user of your project needs their own. HeadlessCanvas is MIT.
| Rendering | Controls UI | Styleable with CSS | Screen-reader accessible | Licence | |
|---|---|---|---|---|---|
| HeadlessCanvas | Canvas | DOM | Yes | Yes | MIT |
| Konva.js | Canvas | Canvas | No | No | MIT |
| Fabric.js | Canvas | Canvas | No | No | MIT |
| tldraw | DOM/SVG | DOM | Yes | Partial | Not open source |
| Excalidraw | Canvas | DOM | It is an app, not a reusable library | — | MIT |
npm install @headless-canvas/core @headless-canvas/uiimport { Editor } from '@headless-canvas/core'
import { createDefaultControls } from '@headless-canvas/ui'
import '@headless-canvas/ui/styles.css'
const editor = new Editor({ container: document.querySelector('#app')! })
createDefaultControls(editor)
editor.createShape({ type: 'rect', x: 40, y: 40, width: 160, height: 110 })That is the whole setup. Getting started covers the rest.