Working with Figma text through the Figma Plugin API is a lot trickier than you might think. All the text inside Figma files are nodes called TextNodes. Essentially, nodes are layers in Figma. With text nodes you have to think about mixed styles, missing fonts and loading fonts.
For now, we concentrate on loading fonts.
If you wish to change the content of a TextNode, you must load its font.
TL;DR
Here's one way of loading a font and manipulating text:
// Load font via async function
const myFontLoadingFunction = async () => {
await figma.loadFontAsync({ family: "Work Sans", style: "Bold" })
}
// Another function where we use the loaded font
const myAnotherFunction = () => {
// Create text layer
const myTextLayer = figma.createText()
// Set the font
myTextLayer.fontName = { family: "Work Sans", style: "Bold" }
// Set text to uppercase
myTextLayer.textCase = "UPPER"
// Set text content
myTextLayer.characters = "This is my title"
// Add text layer to current page in Figma
figma.currentPage.appendChild(myTextLayer);
}
// Use font only after the Promise is resolved
myFontLoadingFunction().then(() => {
myAnotherFunction()
})
That's basically it. If you want to know more about this subject, just keep on reading.
Glossary
You can find the official Figma Plugin documentation page about TextNodes here but I believe the docs could be better and that's why I wrote this blog post.
About loading fonts
The docs tells us this important thing about text and fonts:
The important thing with text is that changing the content of a text node requires its font to be loaded and that fonts are not always available. If you attempt to change, say,
fontName
without first loading the font for that text node, the plugin will throw an exception.
I found out that the exception will look like this in your console.
So, basically every time you make changes to text content or its properties, you have to load its font. Only when you're changing properties like fill colour or stroke, you do not need to load the fonts.
How to load fonts
TextNodes have a property called fontName
which is a javascript object that contains the font family and font style. The default font is { family: "Roboto", style: "Regular" }
. In our example we want to use Work Sans, Bold.
(As a sidenote: You can load any font thats already accessible in the Figma editor. You cannot load fonts from the internet.)
The documentation says that "Loading a font is done via figma.loadFontAsync(fontname)
" and maybe for someone that is enough but, as a designer, I was a bit confused when I tried it and it didn't work.
// Like in the docs => figma.loadFontAsync(fontname)
figma.loadFontAsync({ family: "Work Sans", style: "Bold" })
On it's own, this code isn't enough. This is when the error appears in the console. As we dive deeper into the docs we find this about the loadFontAsync property:
(loadFontAsync) Makes a font available in the plugin for use when creating and modifying text. Calling this function is necessary to modify any property of a text node that may cause the rendered text to change, including .characters, .fontSize, .fontName, etc.
And from it's signature (found in the docs) loadFontAsync(fontName: FontName): Promise<void>
we can see that it returns a Promise. So, we must enchance our code by creating an "async/await" function:
const myFontLoadingFunction = async () => {
await figma.loadFontAsync({ family: "Work Sans", style: "Bold" })
}
After the loadFontAsync Promise is resolved, we can use the then()
method that returns a new Promise and when that is a success we can do what we initially wanted.
myFontLoadingFunction().then(() => {
// Success!
// Add your code here to do something with the loaded font!
})
You can read more about Promises and the then()
from the MDN docs.
All the code once more:
// Load font via async function
const myFontLoadingFunction = async () => {
await figma.loadFontAsync({ family: "Work Sans", style: "Bold" })
}
// Another function where we use the loaded font
const myAnotherFunction = () => {
// Create text layer
const myTextLayer = figma.createText()
// Set the font
myTextLayer.fontName = { family: "Work Sans", style: "Bold" }
// Set text to uppercase
myTextLayer.textCase = "UPPER"
// Set text content
myTextLayer.characters = "This is my title"
// Add text layer to current page in Figma
figma.currentPage.appendChild(myTextLayer);
}
// Use font only after the Promise is resolved
myFontLoadingFunction().then(() => {
myAnotherFunction()
})
What can you do with fonts and text
After you have your fonts loaded you can use the following properties and functions of a TextNode:
- characters = set/write your text content
- fontSize = set font size
- fontName = set font family and style/weight
- textStyleId = set TextStyle using TextStyle id
- textCase = set text casing to uppercase etc.
- textDecoration = set decoration to underline/strikethrough
- letterSpacing = set letter spacing in pixels or percents
- lineHeight = set line height in pixels or percents
- setRangeFontSize() = set font size to characters in range
- setRangeFontName() = set font to characters in range
- setRangeTextCase() = set text casing to characters in range
- setRangeTextDecoration() = set text decoration to characters in range
- setRangeLetterSpacing() = set letter spacing to characters in range
- setRangeLineHeight() = set line height to characters in range
- setRangeTextStyleId() = set TextStyle to characters in range
You can check out all the TextNode properties and functions here.
Have fun developing Figma plugins 🔥 I hope you found this article helpful!
Follow me on Twitter for more Figma, CSS and Design System content 💪
Top comments (0)