Remotion: Create Animated Videos Using HTML, CSS and React

Creating a video with text, animations, colors, and shapes traditionally requires specialist software and potentially years of motion graphic training. What if you could use your existing toolset, training, and background in web development to do the same?

Remotion allows JavaScript developers to reuse the skills and knowledge they’ve built up to create complex animated videos using HTML, CSS, and React JS. If you can render text with React, animate a CSS style, or organize HTML content, you can now create and edit your own videos using solely code, with no video editing applications or software required.

In this article, I’ll go through the process of using Remotion and talk you through my discoveries as we go along.

You can find the complete code for this article on GitHub.

Remotion: What, and Why?

Remotion is a video creation toolkit for React created by Jonny Burger. This toolkit allows anyone with a basic understanding of React, HTML or CSS to create animated videos using code.

In the video creation space there’s currently a high barrier to entry due to the required software and training needed to use and master these tools. By utilizing JavaScript developers’ existing toolkits, this opens the video creation space to a wider user base. As videos become code, we can leverage existing patterns to allow for more effective video creation — such as automated generation based on parameters or build pipelines.

Getting Started

Thankfully, Remotion has a quick and easy setup process with a Yarn and npm starter kit. For this example, we’ll be sticking with npm as the build and run tool. Before we get started, you’ll need to have Node and npm installed. (For assistance, you can follow this guide to installing Node and npm.) Also check the Remotion installation guide if you’re on Linux, as you may need to install additional tools. After getting Node and npm set up, let’s create a new project by running this code:

npm init video

This will prompt you for a project name, which is also used as the directory name. In our case, it will be my-video. Once entered, we can move into the my-video directory and start the default video project by running the start script as follows:

cd my-video npm start

After running the start command, the browser should automatically open. If not, open the browser and navigate to http://localhost:3000/. This feature allows you to watch and debug the video you’re creating. The player has controls that include a play button, which allows you to preview the video content. It may also be useful to start by looking at the code for the demo example, which Remotion provides as a guide for how to build your own video.

Hello, World!

We’re going to create our own video animating the text “Hello, World!”, to get to grips with the components and processes supplied in Remotion.

First of all, let’s delete the existing example code (everything in the src folder), as we want to start afresh. Then, let’s create a Demo directory under the src directory, which will hold and manage all our video work for this project. Inside the Demo directory, create a Demo.js file:

import {Composition, interpolate, Sequence, useCurrentFrame, useVideoConfig} from 'remotion'; import Title from './Title'; import Hello from './Hello'; import "./demo.css"; const Demo = () => { return ( <div className="main-container"> {/* TODO: add video content */} </div> ); }; export const DemoVideo = () => { return ( <Composition id="Demo" component={Demo} durationInFrames={150} fps={30} width={1920} height={1080} defaultProps={{ titleText: 'This is my first Remotion video', titleColor: 'blue', }} /> ) }

The Demo file exports our video code. As you can see, we can create a Demo component that will hold all the visual elements in our video. We can then export a component that renders the Composition of our video. The Composition component allows us to define some basic properties such as the width and height of the video clip, the FPS (frames per second), and the feature that will be rendered. We also import some utils and hooks from Remotion and some additional components that we will create soon.

Currently our Demo component is empty, but let’s add some elements to our video:

const Demo = ({titleText, titleColor}) => { const frame = useCurrentFrame(); const videoConfig = useVideoConfig(); const totalOpacity = interpolate( frame, [videoConfig.durationInFrames - 25, videoConfig.durationInFrames - 15], [1, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', } ); return ( <div className="main-container"> <div style={{opacity: totalOpacity}}> <Sequence from={0} durationInFrames={videoConfig.durationInFrames / 2}> <Hello/> </Sequence> <Sequence from={35} durationInFrames={Infinity}> <Title titleText={titleText} titleColor={titleColor} /> </Sequence> </div> </div> ); };

We’ve added a lot to the file, so let’s break this all down.

Firstly in our render section, we can see from the file that we can now return a div with opacity styles, allowing us to fade elements in and out at the start and end of the video. For the opacity value, we use a Remotion helper. The interpolate function allows you to better define animations and map the animation values to the current frame and the video duration. In this example, we pass in the current frame. The function will get called on each frame generated. The input range is calculated from the duration of the video and the output value ranges from 0 to 1, as this is the range for the opacity CSS value. As the Demo component is re-rendered for each frame, the interpolate function is called each time and will return the appropriate opacity value.

Next, we can begin rendering different visual elements on the video screen. In this example, we want the text “Hello, World!” to fade into view then disappear and the text “This is my first Remotion video” to then appear afterwards. To do so, we can render multiple Sequence components.

A Sequence component is another Remotion feature that allows us to define how and when a component renders in a video and for how long. This is great for building complex videos where you want to add timed or layered elements, such as this example. Each Sequence will also show in the browser player and be titled based on the child component name. This allows you to monitor the video you’re generating and the effects you’re adding to it in real time.

Remotion also provides some useful React hooks, and in this example we make use of the useCurrentFrame and useVideoConfig hooks. useCurrentFrame will return the current frame that the video is on, which is useful for animations and implementing actions based on where the current position of the video playback is. useVideoConfig will return an object with different values, such as:

  • width: the width of the video — useful for positioning elements in the video
  • height: the height of the video — useful for positioning elements in the video
  • FPS: frames per second — which can be used to determine the speed of animation or element movement
  • durationInFrames: the total length of the video in frames — which can be used to calculate animations or times for Sequence show and hide.

In our case, as mentioned, firstly we want our Hello component, the text “Hello, World!”, to appear at the start of the video and remain on screen for half of the time. We do this by using the videoConfig.duration value, which we’ve calculated from the useVideoConfigHook.

For the second Sequence, we want our Title component text, “This is my first Remotion video”, to appear after 35 frames and stay on screen for the full duration of the video. To achieve this, for From we enter 35, and for durationInFrames we enter Infinity.

To style our demo component, we can use CSS along with inline styles. When using CSS, we want to apply styles to the whole video, so let’s create a demo.css file that will hold any styles that cover the whole video area. In our example, we want to make the background white and align out items with Flexbox:

.main-container { flex: 1; background-color: white; }

Now let’s delve deeper into these elements we’re rendering.

Rendering React Components in an Animation

The Hello component is going to be a basic React component that renders an H1 tag with some inline styles applied and the text “Hello, World!” This is the simplest form of a component we can render. For simplicity’s sake, we can use inline styles. But because this is React, you could also import styles from a CSS file and use a class name, styled-components, CSS modules, or any styling pattern you’re already familiar with as an alternative. Let’s create the Hello component. Inside the Demo folder, create a new file Hello.js:

const Hello = () => { return ( <h1 style={{ fontFamily: 'SF Pro Text, Helvetica, Arial', fontWeight: 'bold', fontSize: 100, textAlign: 'center', position: 'absolute', bottom: 500, width: '100%' }} > Hello, World! </h1> ); }; export default Hello;

Now, let’s take a look at a more complex example. In the Demo folder, create a new file called Title.js and add in the component code below:

import {spring, useCurrentFrame, useVideoConfig} from 'remotion'; const Title = ({titleText, titleColor, bottom}) => { const videoConfig = useVideoConfig(); const frame = useCurrentFrame(); const text = titleText.split(' ').map((t) => ` ${t} `); return ( <h1 style={{ fontFamily: 'SF Pro Text, Helvetica, Arial', fontWeight: 'bold', fontSize: 100, textAlign: 'center', position: 'absolute', bottom: bottom || 160, width: '100%', }} > {text.map((t, i) => { return ( <span key={t} style={{ color: titleColor, marginLeft: 10, marginRight: 10, transform: `scale(${spring({ fps: videoConfig.fps, frame: frame - i * 5, config: { damping: 100, stiffness: 200, mass: 0.5, }, })})`, display: 'inline-block', }} > {t} </span> ); })} </h1> ); }; export default Title;

We have a lot going on here, so again let’s break down what’s going on.

Remotion has first-class support for TypeScript. This is not required, but it can make the development process better, as you’ll get more detailed autocomplete suggestions in your IDE. However, to make this example more beginner friendly, we’ll just use normal JavaScript.

Our component takes in two props — titleText and titleColor — which will be used later in our render method. This shows that, using React, we can still pass props around the application, therefore making our video elements reusable and dynamic. You may have noticed that, in our Demo component, we passed props in from the Composition component. This shows the power of React in action. We can pass in props from the very top of the React application, making the video responsive, and meaning you could change one block of text to make a new video or to change the whole video context.

After we’ve accessed our props in the Title component, we call the Remotion hooks again to get the videoConfig and frame data. The Title component then breaks the text prop passed and renders it one word at a time using a combination of a map and CSS transform. Here we have the opportunity to use another built-in helper function. Spring takes in values to help generate a smooth output for the animation value. We pass the main video config’s FPS to control the speed of the animation. The frame value controls when the animation starts, and finally we pass in additional configuration options to control the smoothness of the animation.

After we have all our video components created and ready to go, we need to finally create an index.js file in the root of the src folder and add the following content:

import {registerRoot} from 'remotion'; import { DemoVideo } from './Demo/Demo'; registerRoot(DemoVideo);

The index file imports the registerRoot function from Remotion, which allows us to render the video content. Think of this as the ReactDOM render function but for Remotion. Then we pass our DemoVideo component to registerRoot, which will visualize the rendered video in either development or build modes.

We’re now importing the Demo video that will get rendered by Remotion.

Now that we have all of these features combined, we have a fully animated video that provides one example of the different components and helper functions supplied by Remotion.

We can run the video from the root of the project with the following command:

./node_modules/.bin/remotion preview src/index.js

Or, you can update the start script in the package.json file:

- "start": "remotion preview src/index.tsx", + "start": "remotion preview src/index.js",

Then run the animation using npm start.

Continue reading Learn Remotion: Create Animated Video with HTML, CSS & React on SitePoint.

Similar Posts