Skip to main content

Best practices for @remotion/layout-utils

Take note of the following points to ensure correct measurements when using the @remotion/layout-utils package.

These tips apply to all of measureText(), fitText(), and fillTextBox().

Wait until the font is loaded

Only call measureText() after the font is loaded. This applies to Google Fonts (example below) or any other font loading mechanism.

MyComp.tsx
tsx
import { useState, useEffect } from "react";
import { Dimensions, measureText } from "@remotion/layout-utils";
import { loadFont, fontFamily } from "@remotion/google-fonts/Inter";
 
const { waitUntilDone } = loadFont("normal");
 
const MyComp: React.FC = () => {
const [dimensions, setDimensions] = useState<Dimensions | null>(null);
 
useEffect(() => {
// Wait until the font is loaded before measuring text
waitUntilDone().then(() => {
const measurement = measureText({
fontFamily: fontFamily,
fontSize: 14,
fontWeight: "400",
text: "Hello world",
});
 
// We don't need to use delayRender() here, becuase
// font loading from @remotion/google-fonts is already wrapped in it
setDimensions(measurement);
});
}, []);
 
return null;
};
MyComp.tsx
tsx
import { useState, useEffect } from "react";
import { Dimensions, measureText } from "@remotion/layout-utils";
import { loadFont, fontFamily } from "@remotion/google-fonts/Inter";
 
const { waitUntilDone } = loadFont("normal");
 
const MyComp: React.FC = () => {
const [dimensions, setDimensions] = useState<Dimensions | null>(null);
 
useEffect(() => {
// Wait until the font is loaded before measuring text
waitUntilDone().then(() => {
const measurement = measureText({
fontFamily: fontFamily,
fontSize: 14,
fontWeight: "400",
text: "Hello world",
});
 
// We don't need to use delayRender() here, becuase
// font loading from @remotion/google-fonts is already wrapped in it
setDimensions(measurement);
});
}, []);
 
return null;
};

Use the validateFontIsLoaded optionv4.0.136

Pass validateFontIsLoaded: true to any of measureText(), fitText(), and fillTextBox() to validate that the font family you passed is actually loaded.

This will take a second measurement with the fallback font and if it produces the same measurements, it assumes the fallback font was used and will throw an error.

note

In Remotion v5, this will become the default.

Match all font properties

When measuring text, ensure that all font properties match the ones you are going to use in your video.
This includes fontFamily, fontSize, and fontWeight, letterSpacing and fontVariantNumeric.

You could make reusable variables that you reference in both the measuring function and the actual component.

Using variables for font properties
tsx
import { measureText } from "@remotion/layout-utils";
 
const text = "Hello world";
const fontFamily = "Inter";
const fontWeight = "bold";
const fontSize = 16;
 
// Use the variable in the measurement function:
measureText({
text,
fontFamily,
fontWeight,
fontSize,
});
 
// As well as in markup
<div style={{ fontFamily, fontWeight, fontSize }}>{text}</div>;
Using variables for font properties
tsx
import { measureText } from "@remotion/layout-utils";
 
const text = "Hello world";
const fontFamily = "Inter";
const fontWeight = "bold";
const fontSize = 16;
 
// Use the variable in the measurement function:
measureText({
text,
fontFamily,
fontWeight,
fontSize,
});
 
// As well as in markup
<div style={{ fontFamily, fontWeight, fontSize }}>{text}</div>;

Be aware of borders and padding

Adding a padding or a border to a word will skew the measurements.
Avoid using padding altogether and use the natural spacing between words.
Instead of border, use an outline to add a line outside the text without affecting its layout.

Whitespace

When measuring, the Layout utils will wrap the text in a <span> with display: inline-block and white-space: pre applied.
This will also measure the width of the whitespace characters.

Add those two CSS properties to your markup as well to match it with the measurements.

Server-side rendering

The layout utilities need to be run in a browser.
If you are using them in a component that will be server-side rendered, then we recommend you call the functions in a useEffect, like on the first example on this page.