CSS Text Styles in Figma: Line Height, Letter Spacing, and Per-Run Formatting
CSS and Figma describe line height and letter spacing differently. Here is how each maps, how per-run formatting works, and what to check after an import.
Short answer
CSS text styles map to Figma text properties, but the models differ. Line height is Auto, pixels or a percentage of font size in Figma, while CSS allows normal, a unitless number, a length or a percentage. Letter spacing adds space to the font's default in CSS, and Figma applies it to a whole layer or a selection. Inline formatting such as bold, links and colour becomes separate runs inside one text layer. This page shows how each maps and what to check after an import.
Line height: Auto, px and percent in Figma, four shapes in CSS
What Figma stores
By default, Figma sets line height to Auto, calculated from the font's default line height. You can also set a fixed value in pixels (px) or a percentage of the font size. Switching between fixed and percentage makes Figma convert the value to the nearest pixel, so a round trip can shift a value by a fraction of a pixel.
Plugin code sees the same three options: a LineHeight is either { value, unit: "PIXELS" }, { value, unit: "PERCENT" } or { unit: "AUTO" }, as the Figma plugin docs define it.
What CSS can say
The MDN reference for line-height lists four shapes:
| CSS value | Meaning | Closest Figma value |
|---|---|---|
normal | Chosen by the browser from the font; roughly 1.2 on desktop browsers | Auto |
1.5 (unitless number) | Number times the element's own font size | Percent (150%) or px |
24px (length) | Fixed length | px |
150% (percentage) | Percent of the element's own font size | Percent |
The table compares the value after the browser resolves it. It is not a promise about how any tool converts.
Why inheritance matters
A unitless number is recomputed on every element that inherits it, from that element's own font size. A length or percentage is turned into an absolute length first, and descendants inherit that fixed length. MDN's example makes it concrete: an h1 at 30px with line-height: 1.1 gets 33px, but the same h1 inheriting 1.1em from a 15px parent gets 16.5px.
Two headings can look identical in the browser and still resolve to different numbers. Read the resolved value in dev tools, not the rule you think applies.
What to check
- Compare the resolved line height of one heading and one body paragraph with the value in Figma.
- Expect Auto to differ from
normalwhen the font changes, because both depend on the font. - If the numbers match but the lines look different, check the font before anything else.
Letter spacing: extra space, not a replacement
In CSS, letter-spacing specifies extra inter-character space in addition to the default spacing. The normal keyword differs from 0: it lets the browser adjust spacing to justify text. Percentages are relative to the width of the font's space character, and negative values are allowed but may be limited by the browser.
Two consequences matter in a design file:
- Ligatures turn off. When
letter-spacingis non-zero, browsers do not apply optional ligatures such asligaandclig. Text that shows a ligature at0may not show it once tracking is set. - Very negative values overlap letters. MDN warns that large negative values can make words unrecognizable, so check tight headings by eye.
Figma lets you adjust letter spacing for a whole text layer or for a selection of text. Its help article gives a conversion hint: one unit of tracking (1/1000em) is approximately equal to 0.001em of letter-spacing in CSS. If you select text with different letter spacing values, Figma scales the letter spacing proportionally.
Pick an uppercase label and a body paragraph to test. Labels usually carry positive tracking, so a mismatch shows up there first.
One text layer, several runs
A run is a stretch of characters that share the same styling. CSS creates runs wherever an inline element changes the style: a <strong>, an <a>, a <span style="color: ...">. In Figma, one text layer can hold many runs.
Figma's plugin API exposes each run as a StyledTextSegment, with its own fontName, fontSize, fontWeight, textDecoration, textCase, lineHeight, letterSpacing, fills and hyperlink, plus paragraphSpacing. That's why one paragraph can hold a bold word, a linked phrase and a coloured number without becoming four layers.
Mixed values
When characters in one layer disagree on a property, Figma has no single value to show. The plugin docs say to always consider that a text property could have mixed values, and the API returns the special value figma.mixed. In the interface, the field reads Mixed. Select a smaller range to see each run's value.
Some properties apply to selections as well. Text decoration (underline, strikethrough) and letter case (uppercase, lowercase, capitalize, small caps) can be set on selected text, and letter case is a non-destructive change. Paragraph spacing is a pixel value.
Fonts decide what your text styles do
Line height Auto and glyph widths both come from the font. If the font in the file is not the font on the page, every number above can be right and the text still wraps differently. Figma's plugin docs note that missing fonts are very common in real files, and that an unloaded font is not the same thing as a missing one.
When an import swaps a font, treat the line height and letter spacing as unverified until the font is fixed. In UnHTML, every substitution is listed in the import report. For the mechanics, read how font substitution works in Figma, and for numbers, font substitution in web-to-Figma imports.
What to check after an import
Start with the largest text and work down:
- Headings. Compare resolved line height and letter spacing with Figma. Tight headings expose both.
- Body text. A unitless
line-heightsuch as1.6should read as 160% or the matching px value. - Uppercase labels. Check tracking and letter case.
- Inline runs. Click into a paragraph with a link or bold word and confirm the range, not the whole layer, carries the style.
- Fonts. Resolve substituted fonts first, then recheck steps 1 to 3.
- Wrapping. Text that wraps differently usually points at width or auto layout, as covered in flexbox becoming auto layout.
As of 2026, these are the documented Figma behaviours. UnHTML produces editable layers, not a pixel-exact clone, so treat this list as a real review pass.
Conclusion
Line height, letter spacing and runs each have a different model in CSS and Figma. Compare the resolved CSS value with the Figma value, expect Auto and normal to move with the font, and check ranges rather than whole layers. Start with the fonts, because most text mismatches begin there.
Frequently Asked Questions
Why does my imported line height look different from the page?
CSS line-height can be normal, a unitless number, a length or a percentage, and Figma stores Auto, pixels or a percentage of font size. The result depends on the font and on how the value was inherited on the page. Compare the resolved value in dev tools with the value in Figma.
Does letter-spacing convert one to one?
Not by eye. CSS letter-spacing is extra space added to the font's default spacing, often written in em or px. Figma's own tracking tip equates 1/1000em of tracking to 0.001em in CSS. Check the value on a sample heading.
Can one text layer hold different styles?
Yes. A Figma text layer can carry several runs, each with its own font, size, line height, letter spacing, decoration and colour. Select a range to see or change a single run.
What does Mixed mean in a text field?
It means the selected characters do not share one value for that property. Select a smaller range to see each value.
Questions
- Why does my imported line height look different from the page?
- CSS line-height can be `normal`, a unitless number, a length or a percentage, and Figma stores Auto, pixels or a percentage of font size. The result depends on the font and on how the value was inherited on the page. Compare the resolved value in dev tools with the value in Figma.
- Does letter-spacing convert one to one?
- Not by eye. CSS letter-spacing is extra space added to the font's default spacing, often written in em or px. Figma's own tracking tip equates 1/1000em of tracking to `0.001em` in CSS. Check the value on a sample heading.
- Can one text layer hold different styles?
- Yes. A Figma text layer can carry several runs, each with its own font, size, line height, letter spacing, decoration and colour. Select a range to see or change a single run.
- What does Mixed mean in a text field?
- It means the selected characters do not share one value for that property. Select a smaller range to see each value.