When the DOM and CSS are not enough, reach for these APIs; the Web Graphics volume of this series covers them in depth.
| API | Use it for | Support | Libraries |
|---|---|---|---|
| Canvas 2D | Charts, 2D games | Widely available | Chart.js 38,651 , Konva |
| SVG DOM | Scalable vector shapes | Widely available | D3.js 18,089 , GSAP 88,281 |
| WebGL 2 | GPU 3D (OpenGL ES 3.0) | Widely available | three.js 30,815 , Babylon.js 89,603 |
| WebGPU | Rendering, GPU compute | Chrome 113 1 +, Safari 26 10 | three.js, Babylon.js |
| WebAssembly | Compiled C, C++, Rust | Widely available | Emscripten 175,027 , wasm-pack |
| OffscreenCanvas | Drawing in a worker | Widely available | three.js |
| WebXR | VR and AR sessions | Chromium 4,389 only | A-Frame 172,534 |
Firefox 141 555 added WebGPU on Windows. The demo spells out a WebAssembly module byte by byte: the \0asm header, then sections for addTwo (local.get 0, local.get 1, i32.add). Real modules come from Emscripten, wasm-pack or Go and load with WebAssembly.instantiateStreaming(fetch('app.wasm')), which requires the application/wasm MIME type.
<canvas id="c" width="120" height="40"></canvas>
<svg width="60" height="40"><path id="p" d="M10 4 L34 36" stroke="#2e7d32" stroke-width="4"/></svg>
<ul id="out" style="font: 15px system-ui; margin: 0"></ul>
<script type="module">
const show = (k, v) => out.insertAdjacentHTML('beforeend', `<li>${k}: <b>${v}</b></li>`);
const ctx = c.getContext('2d');
ctx.fillStyle = '#1565c0'; ctx.fillRect(0, 0, 120, 40);
show('Canvas pixel', ctx.getImageData(60, 20, 1, 1).data.join());
show('SVG path length', p.getTotalLength());
show('WebGL 2', document.createElement('canvas').getContext('webgl2') ? 'yes' : 'no');
show('WebGPU adapter', (await navigator.gpu?.requestAdapter()) ? 'found' : 'none');
show('OffscreenCanvas, WebXR', `${'OffscreenCanvas' in window}, ${'xr' in navigator}`);
const wasm = [0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3, 2, 1, 0, 7, 10,
1, 6, 97, 100, 100, 84, 119, 111, 0, 0, 10, 9, 1, 7, 0, 32, 0, 32, 1, 106, 11];
const { instance } = await WebAssembly.instantiate(new Uint8Array(wasm));
show('addTwo(40, 2)', instance.exports.addTwo(40, 2));
</script>
Two smaller pieces sit underneath. The Geometry interfaces — DOMMatrix, DOMPoint, DOMRect, DOMQuad, Baseline Widely available — are the types Canvas, SVG, CSS transforms and getBoundingClientRect() all speak, so new DOMMatrix().translate(10, 20).scale(2) composes a transform without string concatenation. The CSS Painting API (Houdini) registers a worklet with CSS.paintWorklet.addModule() so a paint(myBorder) value draws a background with a Canvas-like context; Chromium 65 only, so declare a plain background-image first.
requestAdapter() resolves to null without a usable GPU, so keep a WebGL fallback. Draw in a worker via transferControlToOffscreen() (Dedicated Web Workers) to protect INP, and give canvas content a text alternative.