Skip to content

Commit b58a811

Browse files
Merge pull request #933 from heygen-com/05-18-feat_registry_add_blend-difference_text_effect_component
feat(registry): add blend-difference text effect component
2 parents eb3c9d7 + 75a34d3 commit b58a811

6 files changed

Lines changed: 265 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
title: "Blend Difference"
3+
description: "Auto-inverting captions using mix-blend-mode: difference — text flips between white and black per-pixel against the background"
4+
---
5+
6+
# Blend Difference
7+
8+
Auto-inverting captions using mix-blend-mode: difference — text flips between white and black per-pixel against the background
9+
10+
`text` `effect` `blend-mode` `contrast` `inversion`
11+
12+
## Install
13+
14+
<CodeGroup>
15+
16+
```bash Terminal
17+
npx hyperframes add caption-blend-difference
18+
```
19+
20+
</CodeGroup>
21+
22+
## How It Works
23+
24+
White text with `mix-blend-mode: difference` inverts per-pixel against whatever is behind it:
25+
26+
- **Dark background** → text stays white
27+
- **Light background** → text flips to black
28+
- **Color background** → text becomes the complement (blue → orange, red → cyan)
29+
30+
The composition root needs `isolation: isolate` so the blend operates against sibling content (video, images) rather than the page background.
31+
32+
## Variants
33+
34+
| Class | Blend Mode | Effect |
35+
| --- | --- | --- |
36+
| `.blend-difference` | `difference` | Hard per-pixel inversion — maximum contrast |
37+
| `.blend-difference-soft` | `exclusion` | Softer inversion — less harsh on midtones |
38+
| `.blend-difference-screen` | `screen` | Text glows on dark areas, fades on light |
39+
40+
## Example
41+
42+
```html
43+
<div data-composition-id="root" style="isolation: isolate;">
44+
<video src="video.mp4" muted playsinline
45+
data-start="0" data-duration="30" data-track-index="0" />
46+
47+
<div class="clip blend-difference"
48+
data-start="0" data-duration="5" data-track-index="1"
49+
style="position: absolute; inset: 0; z-index: 10;
50+
display: flex; align-items: center; justify-content: center;">
51+
<span style="font-size: 120px; font-weight: 800;">
52+
YOUR CAPTION
53+
</span>
54+
</div>
55+
</div>
56+
```
57+
58+
## CSS Custom Properties
59+
60+
| Property | Default | Description |
61+
| --- | --- | --- |
62+
| `--blend-caption-color` | `white` | Base text color before blending |
63+
| `--blend-mode` | `difference` | Override blend mode on `.blend-difference` |
64+
65+
## Details
66+
67+
| Property | Value |
68+
| --- | --- |
69+
| Type | Component |
70+
71+
## Files
72+
73+
| File | Target | Type |
74+
| --- | --- | --- |
75+
| `caption-blend-difference.html` | `compositions/components/caption-blend-difference.html` | hyperframes:snippet |
76+
77+
## Usage
78+
79+
Open `compositions/components/caption-blend-difference.html` and paste its contents into your composition. See the comment header in the file for detailed instructions.

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
{
220220
"group": "Effects",
221221
"pages": [
222+
"catalog/components/caption-blend-difference",
222223
"catalog/components/grain-overlay",
223224
"catalog/components/grid-pixelate-wipe",
224225
"catalog/components/shimmer-sweep",
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<!--
2+
Blend Difference — auto-inverting captions via mix-blend-mode.
3+
4+
Text color inverts per-pixel against whatever is behind it:
5+
white stays white on dark areas, flips to black on light areas.
6+
On color video, white inverts to the complement (blue → orange,
7+
red → cyan, green → magenta).
8+
9+
Setup:
10+
1. The composition root (or a shared ancestor of both the video
11+
and the caption layer) MUST have `isolation: isolate` so the
12+
blend operates against sibling content, not the page background.
13+
2. Add class="blend-difference" to any caption container.
14+
3. Set caption text color to white. The blend mode handles the rest.
15+
16+
Works on any element — divs, spans, SVG text, even images.
17+
18+
Customize:
19+
- --blend-caption-color: base text color (default white)
20+
- Change blend mode via --blend-mode to 'exclusion' for a softer effect
21+
22+
Variants:
23+
- .blend-difference → standard per-pixel inversion
24+
- .blend-difference-soft → exclusion mode, less harsh contrast
25+
- .blend-difference-screen → text glows on dark, fades on light
26+
-->
27+
28+
<style>
29+
.blend-difference {
30+
mix-blend-mode: var(--blend-mode, difference);
31+
color: var(--blend-caption-color, white);
32+
pointer-events: none;
33+
}
34+
35+
.blend-difference-soft {
36+
mix-blend-mode: exclusion;
37+
color: var(--blend-caption-color, white);
38+
pointer-events: none;
39+
}
40+
41+
.blend-difference-screen {
42+
mix-blend-mode: screen;
43+
color: var(--blend-caption-color, white);
44+
pointer-events: none;
45+
}
46+
</style>
47+
48+
<!--
49+
Composition setup example:
50+
51+
<div data-composition-id="root" ... style="isolation: isolate;">
52+
53+
<video id="bg" data-start="0" data-duration="30" data-track-index="0"
54+
src="video.mp4" muted playsinline></video>
55+
56+
<div class="clip blend-difference" data-start="0" data-duration="5" data-track-index="1"
57+
style="position: absolute; inset: 0; z-index: 10;
58+
display: flex; align-items: center; justify-content: center;">
59+
<span style="font-size: 120px; font-weight: 800; text-transform: uppercase;">
60+
YOUR CAPTION
61+
</span>
62+
</div>
63+
</div>
64+
65+
66+
Timeline integration — animate captions normally, blend mode is passive:
67+
68+
tl.from(".caption", {
69+
y: 50, opacity: 0, duration: 0.6, ease: "expo.out"
70+
}, 0.2);
71+
72+
73+
Notes:
74+
- isolation: isolate on the composition root is REQUIRED.
75+
Without it, blend mode composes against the page background
76+
(usually white or black) and you get no inversion.
77+
- Works with any GSAP animation — the blend composites every frame.
78+
- For caption containers with multiple text elements, apply the
79+
class to the shared parent, not each text element individually.
80+
- On pure black backgrounds, white text stays white (difference
81+
of white and black = white). The effect is most visible when
82+
the background has varied luminance or color.
83+
-->
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<!--
2+
Blend Difference — auto-inverting captions via mix-blend-mode.
3+
4+
Text color inverts per-pixel against whatever is behind it:
5+
white stays white on dark areas, flips to black on light areas.
6+
On color video, white inverts to the complement (blue → orange,
7+
red → cyan, green → magenta).
8+
9+
Setup:
10+
1. The composition root (or a shared ancestor of both the video
11+
and the caption layer) MUST have `isolation: isolate` so the
12+
blend operates against sibling content, not the page background.
13+
2. Add class="blend-difference" to any caption container.
14+
3. Set caption text color to white. The blend mode handles the rest.
15+
16+
Works on any element — divs, spans, SVG text, even images.
17+
18+
Customize:
19+
- --blend-caption-color: base text color (default white)
20+
- Change blend mode via --blend-mode to 'exclusion' for a softer effect
21+
22+
Variants:
23+
- .blend-difference → standard per-pixel inversion
24+
- .blend-difference-soft → exclusion mode, less harsh contrast
25+
- .blend-difference-screen → text glows on dark, fades on light
26+
-->
27+
28+
<style>
29+
.blend-difference {
30+
mix-blend-mode: var(--blend-mode, difference);
31+
color: var(--blend-caption-color, white);
32+
pointer-events: none;
33+
}
34+
35+
.blend-difference-soft {
36+
mix-blend-mode: exclusion;
37+
color: var(--blend-caption-color, white);
38+
pointer-events: none;
39+
}
40+
41+
.blend-difference-screen {
42+
mix-blend-mode: screen;
43+
color: var(--blend-caption-color, white);
44+
pointer-events: none;
45+
}
46+
</style>
47+
48+
<!--
49+
Composition setup example:
50+
51+
<div data-composition-id="root" ... style="isolation: isolate;">
52+
53+
<video id="bg" data-start="0" data-duration="30" data-track-index="0"
54+
src="video.mp4" muted playsinline></video>
55+
56+
<div class="clip blend-difference" data-start="0" data-duration="5" data-track-index="1"
57+
style="position: absolute; inset: 0; z-index: 10;
58+
display: flex; align-items: center; justify-content: center;">
59+
<span style="font-size: 120px; font-weight: 800; text-transform: uppercase;">
60+
YOUR CAPTION
61+
</span>
62+
</div>
63+
</div>
64+
65+
66+
Timeline integration — animate captions normally, blend mode is passive:
67+
68+
tl.from(".caption", {
69+
y: 50, opacity: 0, duration: 0.6, ease: "expo.out"
70+
}, 0.2);
71+
72+
73+
Notes:
74+
- isolation: isolate on the composition root is REQUIRED.
75+
Without it, blend mode composes against the page background
76+
(usually white or black) and you get no inversion.
77+
- Works with any GSAP animation — the blend composites every frame.
78+
- For caption containers with multiple text elements, apply the
79+
class to the shared parent, not each text element individually.
80+
- On pure black backgrounds, white text stays white (difference
81+
of white and black = white). The effect is most visible when
82+
the background has varied luminance or color.
83+
-->
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
3+
"name": "caption-blend-difference",
4+
"type": "hyperframes:component",
5+
"title": "Blend Difference",
6+
"description": "Auto-inverting text using mix-blend-mode: difference — flips between white and black per-pixel against the background",
7+
"tags": ["text", "effect", "blend-mode", "contrast", "inversion"],
8+
"files": [
9+
{
10+
"path": "caption-blend-difference.html",
11+
"target": "compositions/components/caption-blend-difference.html",
12+
"type": "hyperframes:snippet"
13+
}
14+
]
15+
}

registry/registry.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@
151151
"name": "caption-highlight",
152152
"type": "hyperframes:component"
153153
},
154+
{
155+
"name": "caption-blend-difference",
156+
"type": "hyperframes:component"
157+
},
154158
{
155159
"name": "instagram-follow",
156160
"type": "hyperframes:block"

0 commit comments

Comments
 (0)