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.tsxtsx
import {useState ,useEffect } from "react";import {Dimensions ,measureText } from "@remotion/layout-utils";import {loadFont ,fontFamily } from "@remotion/google-fonts/Inter";const {waitUntilDone } =loadFont ("normal");constMyComp :React .FC = () => {const [dimensions ,setDimensions ] =useState <Dimensions | null>(null);useEffect (() => {// Wait until the font is loaded before measuring textwaitUntilDone ().then (() => {constmeasurement =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 itsetDimensions (measurement );});}, []);return null;};
MyComp.tsxtsx
import {useState ,useEffect } from "react";import {Dimensions ,measureText } from "@remotion/layout-utils";import {loadFont ,fontFamily } from "@remotion/google-fonts/Inter";const {waitUntilDone } =loadFont ("normal");constMyComp :React .FC = () => {const [dimensions ,setDimensions ] =useState <Dimensions | null>(null);useEffect (() => {// Wait until the font is loaded before measuring textwaitUntilDone ().then (() => {constmeasurement =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 itsetDimensions (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.
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 propertiestsx
import {measureText } from "@remotion/layout-utils";consttext = "Hello world";constfontFamily = "Inter";constfontWeight = "bold";constfontSize = 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 propertiestsx
import {measureText } from "@remotion/layout-utils";consttext = "Hello world";constfontFamily = "Inter";constfontWeight = "bold";constfontSize = 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.