Skip to main content

Text highlights

We recommend @remotion/rough-notation to annotate text to add marker highlights, encircle words, box or strike through parts.

Highlight

Use <Highlight> from @remotion/rough-notation for a hand-drawn highlight behind text.

Show code
RoughNotationHighlight.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {Highlight} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Easing, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationHighlight: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, }} > <Interactive.Span>A truly </Interactive.Span> <Highlight name="Highlight annotation" progress={interpolate(frame, [0, 25], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: [ Easing.spring({ damping: 200, mass: 1, stiffness: 100, allowTail: true, durationRestThreshold: 0.02, overshootClamping: false, }), ], })} color={'rgba(255, 236, 79, 0.62)'} maxRandomnessOffset={10} roughness={2.3} padding={{ left: 20, right: 20, }} bowing={0} > remarkable </Highlight>{' '} <Interactive.Span>end to the World cup</Interactive.Span> </Interactive.Div> </AbsoluteFill> ); };

Underline

Use <Underline> to add a drawn underline.

Show code
RoughNotationUnderline.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {Underline} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationUnderline: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, }} > <Interactive.Span>Underline </Interactive.Span> <Underline name="Underline annotation" progress={interpolate(frame, [14, 35], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', })} color={'rgba(53, 95, 143, 0.71)'} strokeWidth={10} iterations={3} > this </Underline>{' '} <Interactive.Span>phrase</Interactive.Span> </Interactive.Div> </AbsoluteFill> ); };

Strike-through

Use <StrikeThrough> to cross out a word with a single line.

Show code
RoughNotationStrikeThrough.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {StrikeThrough} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationStrikeThrough: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, }} > <Interactive.Span>The </Interactive.Span> <StrikeThrough name="Strike-through annotation" progress={interpolate(frame, [10, 25], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', })} color={'#f11515'} strokeWidth={14} > forbidden </StrikeThrough>{' '} <Interactive.Span>fruit</Interactive.Span> </Interactive.Div> </AbsoluteFill> ); };

Crossed-off

Use <CrossedOff> for a stronger removal mark.

Show code
RoughNotationCrossedOff.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {CrossedOff} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationCrossedOff: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, }} > <Interactive.Span>Please </Interactive.Span> <CrossedOff name="Crossed off annotation" progress={interpolate(frame, [18, 39], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', })} color={'#eb2525'} strokeWidth={6} iterations={10} roughness={2} > remove </CrossedOff>{' '} <Interactive.Span>this</Interactive.Span> </Interactive.Div> </AbsoluteFill> ); };

Box

Use <Box> to draw a rectangle around text.

Show code
RoughNotationBox.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {Box} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationBox: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, textAlign: 'center', }} > <Interactive.Span>Think outside the </Interactive.Span> <Box name="Box annotation" progress={interpolate(frame, [0, 23], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', })} color={'#fe0000'} strokeWidth={8} iterations={1} padding={{ left: 3, right: 6, top: -12, bottom: -5, }} roughness={0.9} > box </Box> </Interactive.Div> </AbsoluteFill> ); };

Bracket

Use <Bracket> with individual bracket flags to draw selected sides.

Show code
RoughNotationBracket.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {Bracket} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationBracket: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, }} > <Interactive.Span>Mark </Interactive.Span> <Bracket name="Bracket annotation" progress={interpolate(frame, [0, 60], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', })} bracketLeft bracketRight bracketTop roughness={1} bowing={3} strokeWidth={8} color="#dc2626" bracketBottom padding={{ top: -11, }} > this </Bracket>{' '} <Interactive.Span>part</Interactive.Span> </Interactive.Div> </AbsoluteFill> ); };

Circle marker

Use <Circle> when the annotation should sit above the text.

Show code
RoughNotationCircle.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {Circle} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Easing, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationCircle: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, }} > <Interactive.Span>How much </Interactive.Span> <Circle name="Circle annotation" progress={interpolate(frame, [0, 43], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: [Easing.bezier(0.42, 0, 0.58, 1)], })} roughness={1.8} strokeWidth={12} color={'rgba(37, 99, 235, 0.57)'} padding={{ left: 10, right: 10, top: 10, bottom: 10, }} box={'inside'} > circular </Circle>{' '} <Interactive.Span>financing is in AI?</Interactive.Span> </Interactive.Div> </AbsoluteFill> ); };

Animating the seed

Animate seed to redraw an annotation on every frame.

Show code
RoughNotationAnimatedSeed.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {Circle} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationAnimatedSeed: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, textAlign: 'center', }} > <Circle name="Animated seed annotation" progress={1} color={'#2563eb'} strokeWidth={10} roughness={1.8} seed={interpolate(frame, [0, 89], [1, 90], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', })} > motion </Circle> </Interactive.Div> </AbsoluteFill> ); };

Posterized seed

Add posterize to interpolate to lower the frame rate of the seed change.

Show code
RoughNotationPosterizedSeed.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {Circle} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationPosterizedSeed: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, textAlign: 'center', }} > <Circle name="Posterized seed annotation" progress={1} color={'#2563eb'} strokeWidth={10} roughness={1.8} seed={interpolate(frame, [0, 89], [1, 90], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', posterize: 10, })} > motion </Circle> </Interactive.Div> </AbsoluteFill> ); };

Posterizing the progress

Apply posterize to progress to make the circle draw in discrete steps.

Show code
RoughNotationPosterizedProgress.tsx
import {loadFont} from '@remotion/google-fonts/CormorantGaramond'; import {Circle} from '@remotion/rough-notation'; import React from 'react'; import { AbsoluteFill, Interactive, interpolate, useCurrentFrame, } from 'remotion'; const {fontFamily} = loadFont('normal', { weights: ['700'], subsets: ['latin'], }); const containerStyle: React.CSSProperties = { justifyContent: 'center', alignItems: 'center', }; export const RoughNotationPosterizedProgress: React.FC = () => { const frame = useCurrentFrame(); return ( <AbsoluteFill style={containerStyle}> <Interactive.Div style={{ fontSize: 80, fontWeight: 700, lineHeight: 1.1, color: '#171717', fontFamily, width: 800, textAlign: 'center', }} > <Circle name="Posterized progress annotation" progress={interpolate(frame, [0, 43], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', posterize: 10, })} color={'#2563eb'} strokeWidth={10} roughness={1.8} iterations={1} > motion </Circle> </Interactive.Div> </AbsoluteFill> ); };

See also