Skip to main content

HTML-in-canvasv4.0.455

Regular video editors are canvas-based which allows for complex effects and compositing that is not possible with plain CSS.

HTML-in-canvas is an experimental browser API available in Chrome and other Chromium-based browsers behind a flag, which allows you to draw a live DOM node into a <canvas> and post-process it with the Canvas 2D API, WebGL or WebGPU.

Remotion offers a <HtmlInCanvas> component, transitions and HTML-in-canvas-based client-side rendering.

Enabling the flag in Chrome​

To preview HTML-in-canvas effects in the Remotion Studio, use Google Chrome v149 or later and enable a flag:

  1. Install or update Google Chrome.
  2. Open chrome://flags/#canvas-draw-element.
  3. Set the HTML-in-Canvas flag to Enabled and restart.

To check at runtime whether HTML-in-canvas is supported, you can use HtmlInCanvas.isSupported().

For rendering, you don't need to do anything — see Rendering below.

The <HtmlInCanvas> component​

<HtmlInCanvas> is a convenient component which wraps its children in a canvas and allows you to manipulate the content when the canvas is painted.

MyComp.tsx
import {HtmlInCanvas, type HtmlInCanvasOnPaint} from 'remotion'; const onPaint: HtmlInCanvasOnPaint = ({canvas, elementImage}) => { const ctx = canvas.getContext('2d'); if (!ctx) { throw new Error('Failed to acquire 2D context'); } ctx.reset(); ctx.filter = 'blur(8px)'; ctx.drawElementImage(elementImage, 0, 0); }; export const MyComp: React.FC = () => { return ( <HtmlInCanvas width={1280} height={720} onPaint={onPaint}> <div style={{fontSize: 80}}>Hello</div> </HtmlInCanvas> ); };

See the <HtmlInCanvas> reference for the full API, including WebGL and WebGPU examples.

Using the browser API directly​

You can also use the browser API directly. Refer to the working draft to do so.
If you do so, you are responsible yourself for calling delayRender() and continueRender() to synchronize paint operations.

Examples​

Find example components in the remotion-dev/html-in-canvas repository.

Also see the following sample prompts in our prompt gallery that you can give your coding agent:

Example prompts​

/remotion-create Create a sample composition and apply an HTML-in-canvas glitch effect to it.
Suggested prompt
/remotion-create Make a new composition with a subtle CRT convex-shape shader over an HTML element. Use a terminal and Remotion theme. Animate the command and output of "npx create-video@latest --yes --blank my-video", followed by invoking "claude" and entering the prompt "Add a CRT effect using HTML-in-canvas".
Suggested prompt

With @remotion/transitions​

@remotion/transitions can take advantage of HTML-in-canvas as well to blend two scenes.
See zoomBlur() presentation for an example.

You can also build your own — see Making a custom HTML-in-canvas presentation.

Limitations​

HTML-in-canvas is only available in Chrome 149 and later with the chrome://flags/#canvas-draw-element flag enabled.
The API is unstable - Chrome may change the API or even remove it in the future.

Nesting <HtmlInCanvas> components requires Chrome 157.0.8080.0 or newer with HTML-in-canvas enabled. See Nested HTML-in-canvas.

Cross-origin content​

HTML-in-canvas omits cross-origin content that JavaScript cannot read, including images and videos loaded without CORS, cross-origin iframes and tainted canvases. Content can appear in the regular page while being absent from the captured canvas.

From v4.0.542, <Img> and <Html5Video> default to crossOrigin="anonymous" inside <HtmlInCanvas>, including <HtmlInCanvasMotionBlur>. This also applies to <OffthreadVideo> during preview. The media server must allow CORS. In earlier versions, set crossOrigin="anonymous" explicitly.

If the server rejects CORS, these components report a loading error instead of silently disappearing from the canvas. Anonymous CORS omits cross-origin credentials; for authenticated media, see <Img>'s crossOrigin prop or <Html5Video>'s crossOrigin prop.

For native <img> and <video> elements, set crossOrigin="anonymous" yourself. SVG <image> elements also support this attribute. CSS background images have no crossOrigin attribute; use a same-origin URL, a data URL, or a blob URL created from a successful CORS fetch. If a remote server does not allow CORS, host the asset in your public folder.

Rendering​

From v4.0.455, render is supported locally via npx remotion render and Studio, on Lambda, on Vercel and through server-side rendering APIs.

We compiled a version of Chrome and made it the default, and enabled the flag for you.

Nested <HtmlInCanvas> components are supported during server-side rendering from Remotion v4.0.534, which uses Chromium 157.0.8080.0.

If your effect uses a WebGL shader, pass --gl=angle to make the render work:

npx remotion render --gl=angle

Set it as the default in remotion.config.ts so Studio and CLI renders pick it up as a default:

remotion.config.ts
Config.setChromiumOpenGlRenderer('angle');

If your machine has no GPU, we recommend --gl=swangle instead (default on Lambda).

AI agents​

Remotion publishes Agent Skills that teach AI agents like Claude Code, Codex and Cursor how to use <HtmlInCanvas> correctly — including the onInit / onPaint lifecycle, the --gl=angle flag and nesting support.

Install them with:

npx skills add remotion-dev/skills

Leveraging HTML-in-canvas for client-side rendering​

Not directly related, but @remotion/web-renderer can also use this technology to capture frames.

This is opt-in. In browsers without nesting support, compositions containing <HtmlInCanvas> use the built-in DOM composer because native capture would create a nested HTML-in-canvas subtree.

Nested HTML-in-canvas​

Nesting <HtmlInCanvas> components is supported in Chrome 157.0.8080.0 or newer with HTML-in-canvas enabled. Use HtmlInCanvas.isNestingSupported() to check at runtime. Unsupported browsers throw an error when components are nested. Server-side rendering supports nesting from Remotion v4.0.534.

See also​