The descender clipping incident
It was Tuesday morning and my coffee was getting cold. A designer sent me a direct message about the staging environment. The button text looked weird on the new marketing landing page. I opened the browser inspector to take a look.
The font size was correct. The font weight was completely fine. But the line height was hardcoded to exactly 24px instead of inheriting the relative multiplier from our scale. The bounding box of the button was aggressively clipping the bottom half of the lowercase 'g' and 'y' characters. It looked terrible.
I checked the source code. The button component was using a utility class generated straight from our design tokens. But the tokens were not really tokens. They were just a flattened dump of raw CSS properties.
We had spent a month migrating our entire component library to Figma variables. Everyone was really happy with the new setup. But we made a massive mistake with our typography architecture. We flattened everything to raw values.
Why flattened tokens break your UI
Let me explain what happens when you flatten typography variables. You take a beautiful system of semantic aliases and you crush it into static strings. This is a massive anti-pattern.
Your Figma file might actually be set up perfectly. You might have a primitive collection with a variable called {font.size.lg} set to 18px. You bind that variable to a text style called Heading/Small. This is exactly how the tool is meant to be used. The designer did their job perfectly.
Then you run an export script or a basic plugin. The tool looks at the text style and spits out this CSS.
.text-heading-small {
font-family: 'Inter', sans-serif;
font-size: 18px;
font-weight: 600;
line-height: 24px;
letter-spacing: -0.02em;
}
This looks harmless. It's actually a trap. this is the one thing nobody talks about.
You've completely lost the reference to {font.size.lg}. The connection is completely gone. If your accessibility team decides that the large font size needs to bump up to 20px for better readability, you have a huge problem. You can't just update the primitive token. You have to hunt down every single text style that happened to use 18px and manually change it. It defeats the entire purpose of having a tokenised architecture.
Let's look at another concrete example. Think about fluid typography. If you want your type scale to adapt to the viewport using CSS clamp() functions, you need those primitive variables intact. If your headings are hardcoded to 32px, you have to write painful media queries to override them on mobile devices. If they reference a variable, you just redefine the variable at the root level.
You also end up with bizarre output paths. Many basic export scripts include the Figma collection name in the final CSS class. You end up writing .typography-mobile-heading-1 in your React components. This tightly couples your frontend code to the internal file structure of a Figma document. If a designer renames a folder in Figma, your build fundamentally breaks.
The illusion of safety
I understand why developers accept this pattern. Flattening typography feels very safe.
You look at a raw CSS class with hardcoded pixels and you know exactly what the browser will render. It removes the mental overhead of tracking CSS custom properties across five different stylesheets. You don't have to worry about the cascade behaving unpredictably. It's honestly much easier for a junior developer to debug a static 18px value than a chain of three different variable references.
But safe does not scale. When you flatten everything, you aren't building a design system. You're just writing a very complicated static stylesheet.
Keeping the bindings alive
Your typography tokens need to output as proper bound aliases. The final CSS should look like this.
:root {
--font-size-lg: 1.125rem;
--font-weight-semibold: 600;
--line-height-tight: 1.2;
}
.heading-small {
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semibold);
line-height: var(--line-height-tight);
}
This is how you build a resilient system. The text style is just a semantic wrapper around your primitive variables. You can update the base scale once and watch the changes cascade perfectly through every component on your website.
This is exactly why we just shipped Text Styles Export v2 in the Design System Sync plugin. We wanted to fix this specific headache. The new Text Styles tab exports your typography as first-class W3C tokens with $type: typography. It preserves your bound variables as proper aliases instead of crushing them into raw pixels.
It also normalises line height and letter spacing to standard CSS units so you don't get those weird pixel clipping bugs. We even built it to automatically strip out Figma collection names from the output paths. Your generated files stay clean and semantic.
Getting this architecture right took me years of making painful mistakes on large codebases. I actually wrote down everything I learned about token structures and component governance. It turned into a 200-page handbook called "Ship Your Design System" which is now live on Amazon. It covers 23 chapters across foundations, tokens, components, tools, and implementation. Chapter 12 is entirely about this exact token pipeline.
You can check out the plugin at https://ds-sync.netlify.app?utm_source=devto&utm_medium=post&utm_campaign=bot or grab it directly from the Figma Community at https://www.figma.com/community/plugin/1561389071519901700?utm_source=devto&utm_medium=post&utm_campaign=bot. For the book, head over to https://alexanderburgos.netlify.app/books/ship-your-design-system.
So take a look at your generated typography files right now. Are you actually using design tokens, or are you just pretending?
For further actions, you may consider blocking this person and/or reporting abuse
