✦ Open Source
React to Canvas,
pixel-perfect.
A React custom renderer that draws your existing JSX to Canvas instead of DOM. Zero migration. Same code. Different target.
$
npm install react-pxlCanvas (react-pxl)DOM (react-dom)
⬡ Canvas — Single <canvas> element
◇ DOM — Standard react-dom render
Zero Migration
Your existing <div>, <p>, <h1>, <img> components render to canvas as-is. No rewrites needed.
Flexbox Layout
Powered by Yoga WASM — full flexbox support including direction, wrap, gap, align, and justify.
Tailwind Classes
Built-in runtime parser for Tailwind utilities. Use className just like react-dom.
Full Event System
Click, pointer, keyboard, focus, and scroll events with bubbling — mirrors DOM behavior.
Images & Clipping
Async image loading, object-fit modes, and border-radius clipping — all canvas-native.
Dirty-Rect Rendering
Only repaints changed regions. One canvas element instead of thousands of DOM nodes.
Scrollable Lists, on Canvas
200 items in a scrollable container. Plain React list rendering — no virtualization needed. Try scrolling it!
react-pxl vs react-window
1,000 items with dynamic heights (40–200 px). react-pxl uses plain JSX — no virtualization API. react-window needs VariableSizeList + itemSize callback.
⬡ react-pxl — plain overflow: scroll
◇ react-window — VariableSizeList
| Metric | react-pxl | react-window |
|---|---|---|
| FPS (steady-state) | 60 fps | 60 fps |
| Avg frame time | ~2 ms | ~4 ms |
| Virtualization required | No | Yes |
| API complexity | Plain JSX | Render-prop + itemSize callback |
| DOM nodes | 1 (canvas) | ~30 visible rows |
Scroll-Linked Animations
Per-item visual effects driven by scroll position — opacity, scale, parallax, and color shift. Toggle effects on/off and watch the FPS difference.
⬡ react-pxl — scroll effects on canvas
◇ react-window — scroll effects on DOM
| Scenario | react-pxl | react-window |
|---|---|---|
| No effects | 60 fps | 60 fps |
| Opacity only | 60 fps | ~58 fps |
| All 4 effects | 60 fps | ~40–50 fps |
| Why | Canvas redraw: same cost ± effects | DOM: per-item style mutation → reflow/repaint |
Familiar API
Two lines to switch from DOM to Canvas.
import { render } from 'react-pxl'
function App() {
return (
<div style={{ padding: 24, gap: 12, backgroundColor: '#f1f5f9' }}>
<h1 style={{ fontSize: 28, color: '#1e293b' }}>Hello, Canvas!</h1>
<p style={{ color: '#64748b' }}>Same JSX. Different renderer.</p>
</div>
)
}
const canvas = document.getElementById('root')
render(<App />, canvas)Last updated on