DEV Community

Alexander
Alexander

Posted on

Stop using hex codes in your CSS

It happened again last Wednesday. I was looking at a pull request for a new user settings modal. The UI was gorgeous. The React code was incredibly clean. Then I opened the stylesheet. Right there on line 42 was the culprit.

.modal-background {
  background-color: #f3f4f6;
  border: 1px solid #e5e7eb;
  font-size: 14px;
}
Enter fullscreen mode Exit fullscreen mode

I immediately requested changes. My feedback was just three words. Use the tokens.

This might sound incredibly pedantic. You might think I'm just being a difficult reviewer. But hardcoding hex values and raw pixels in modern web development is a fundamental mistake. It's technical debt disguised as a quick fix. We need to stop doing it entirely.

The copy paste trap

I understand exactly why this happens. You're building a complex feature under a very tight deadline. You open the design file to check the specifications. You click on a primary button component. The right sidebar shows a raw hex value instead of a semantic token name.

So you just copy it. You paste it into your code. The component looks exactly like the design on your screen. You push the code to the repository and move on to the next ticket in your sprint.

But that simple copy and paste action breaks the entire chain of truth. Your code is now entirely disconnected from the design system. If the design team decides to update the neutral colour palette next month, your modal will stay exactly the same. It will slowly drift out of sync with the rest of the application.

Eventually someone will have to log a bug ticket. A completely avoidable bug ticket that wastes time for everyone involved.

The dark mode disaster

The biggest issue with raw hex codes appears the moment you try to implement any kind of theming. Most modern applications need to support at least a light mode and a dark mode. Many enterprise apps also need to support high contrast modes for accessibility.

When you use semantic CSS variables, this context switch happens automatically. The browser handles the complexity for you at the rendering level.

:root {
  --surface-primary: #ffffff;
  --text-primary: #111827;
  --border-subtle: #e5e7eb;
}

[data-theme="dark"] {
  --surface-primary: #1f2937;
  --text-primary: #f9fafb;
  --border-subtle: #374151;
}

.card {
  background-color: var(--surface-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
}
Enter fullscreen mode Exit fullscreen mode

This code is resilient. It adapts to the user context perfectly.

If you hardcode #ffffff for that card background instead, you're completely stuck. You now have to write complex media queries or theme override classes for every single component in your entire codebase. I've seen projects where developers manually maintain two completely separate stylesheets just because they refused to adopt CSS variables early on. honestly it is an absolute maintenance nightmare.

It is not just about colours

This problem goes beyond just hex codes. Hardcoding raw typography values is equally destructive.

When a developer writes font-size: 24px instead of using a proper typography token, they break the scaling system. If the design team decides to adjust the typography scale for mobile devices, those hardcoded pixel values will not respond.

Your text styles need to be systematised just as rigorously as your colour palette. Every heading and body paragraph should reference a specific design system text style.

The reality of one off requests

I know exactly what the counter argument is here. You might be thinking about that one specific marketing page you had to build last week. The design called for a very specific neon pink that doesn't exist in your design system. The marketing director insisted on that exact shade.

In that specific scenario, creating a whole new design token might feel like overkill. Sometimes you just need to ship the feature and move on.

I completely agree with that logic. Context matters. If you're building an isolated campaign page that will be deleted in a month, do whatever gets it done fastest. But if you're building core product UI, those hardcoded values will inevitably come back to haunt you.

The silent migration debt

tbh the blame doesn't always fall on the developers. Most of the time developers use raw hex codes because the designers are using raw hex codes in their files.

this is the silent design system migration debt nobody talks about.

A design team will spend two months migrating all their files to use new Figma variables. They announce the successful migration in a massive company meeting. Everyone claps. Then the developers try to inspect the files.

Turns out half the components in the Figma file are still using hardcoded hex values. The designers forgot to actually link the new variables to the component properties. They look correct visually, but structurally they are completely unwired. When a developer inspects the file, they just see #3f82f0 instead of var(--brand-blue).

Fixing the source of truth

I got so incredibly frustrated with this exact cycle. I was tired of finding rogue hex codes in code reviews. I was also tired of constantly telling designers they forgot to wire up their variables.

So basically I built a tool to catch the problem at the source. It's a plugin called Design System Sync.

In the newest update, I added a feature specifically to detect this unwired debt. The plugin scans every single component in your Figma file. It finds exactly which properties still use hardcoded hex values instead of your design system variables. It gives you a clean list showing exactly where the mistakes are so you can fix them before handing off the design.

I also updated the code generation engine. When you export your components, the generated code now outputs actual token references like var(--checkbox-bg-checked) instead of raw background colours. This means developers can copy the code directly and know they are using the correct system values.

It also has a dedicated tab for Text Styles now. You can browse all text styles in the file and export them as CSS classes with the token references fully preserved.

If you're fighting this battle in your own team, you can check out Design System Sync on the web. You can also grab it directly from the Figma Community.

The final check

We need to treat hex codes like we treat inline styles. They are a sign that something has gone wrong in the workflow. The next time you see a six character hash symbol or a raw pixel value in a pull request, push back immediately. Ask where the token is.

Are you still letting developers hardcode colours in your codebase, or have you fully committed to variables?

Top comments (0)