Skip to content

Comments

@remotion/web-renderer: Add support for text shadows#6607

Merged
JonnyBurger merged 2 commits intomainfrom
web-renderer-text-shadow
Feb 20, 2026
Merged

@remotion/web-renderer: Add support for text shadows#6607
JonnyBurger merged 2 commits intomainfrom
web-renderer-text-shadow

Conversation

@JonnyBurger
Copy link
Member

Summary

  • Adds text-shadow CSS property support to the web renderer
  • Parses text-shadow values (offset, blur, color, multiple shadows) and applies them via Canvas 2D shadow API before drawing text
  • Adds visual regression test covering simple shadow, colored shadow, multiple shadows, hard-edge shadow, and glow effects

Closes #6606

Test plan

  • New text-shadow.test.tsx passes on all 3 browsers (chromium, firefox, webkit)
  • bun run build passes
  • bun run stylecheck passes

🤖 Generated with Claude Code

Closes #6606

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 20, 2026 09:08
@vercel
Copy link
Contributor

vercel bot commented Feb 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bugs Ready Ready Preview, Comment Feb 20, 2026 9:35am
remotion Ready Ready Preview, Comment Feb 20, 2026 9:35am

Request Review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for the text-shadow CSS property to the web renderer by parsing text-shadow values and applying them using the Canvas 2D shadow API.

Changes:

  • Implemented parseTextShadow() function to parse CSS text-shadow values including multiple shadows, colors, offsets, and blur radii
  • Modified drawText() to apply parsed shadows before rendering text on the canvas
  • Added comprehensive visual regression test covering various shadow scenarios (simple, colored, multiple, hard-edge, glow)

Reviewed changes

Copilot reviewed 5 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/web-renderer/src/drawing/text/parse-text-shadow.ts New parser to extract text-shadow properties from CSS strings
packages/web-renderer/src/drawing/text/draw-text.ts Applies parsed text shadows to canvas context before drawing text
packages/web-renderer/src/test/fixtures/text/text-shadow.tsx Test fixture demonstrating various text-shadow use cases
packages/web-renderer/src/test/text-shadow.test.tsx Visual regression test for text-shadow rendering
packages/web-renderer/src/test/Root.tsx Registers the text-shadow test composition
Comments suppressed due to low confidence (1)

packages/web-renderer/src/drawing/text/parse-text-shadow.ts:43

  • The regex pattern matches units like em, rem, and %, but parseFloat() on line 44 will fail to convert these relative units to absolute pixel values. Text-shadow offsets and blur radius should be converted to pixels based on the element's computed font size for relative units.
		const numbers = remaining.match(/[+-]?\d*\.?\d+(?:px|em|rem|%)?/gi) || [];

Copy link
Contributor

@pullfrog pullfrog bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean PR that follows the established parseBoxShadow pattern closely. The Canvas 2D shadow approach is sound for opaque text. Two observations below — neither is blocking.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow runpullfrog.com𝕏

Comment on lines +84 to +91
for (let i = textShadows.length - 1; i >= 0; i--) {
const shadow = textShadows[i];
contextToDraw.shadowColor = shadow.color;
contextToDraw.shadowBlur = shadow.blurRadius;
contextToDraw.shadowOffsetX = shadow.offsetX;
contextToDraw.shadowOffsetY = shadow.offsetY;
contextToDraw.fillText(token.text, x, y);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heads up: each shadow pass calls fillText, which draws both the shadow and the text body. So for N shadows the text body is composited N+1 times. For opaque text this is visually correct, but for semi-transparent webkitTextFillColor the text body would appear more opaque than CSS text-shadow renders it.

The box-shadow implementation works around this with destination-out compositing on an offscreen canvas. A similar technique could be applied here for pixel-perfect fidelity, but it's a reasonable trade-off for v1.

- Extract shared `parseShadowValues` from box-shadow and text-shadow parsers
- Update limitations.mdx to mark text-shadow as supported
- Update web-renderer-test skill to mention limitations.mdx

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JonnyBurger JonnyBurger merged commit 1a190b8 into main Feb 20, 2026
14 checks passed
@JonnyBurger JonnyBurger deleted the web-renderer-text-shadow branch February 20, 2026 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web Renderer: Add support for text shadows

1 participant