How to Use Hex Colors as CSS Custom Properties with Opacity
- Store color as --brand-rgb: 59, 130, 246 — the three RGB channel values, not the hex string.
- Use it with rgba(): background: rgba(var(--brand-rgb), 0.5);
- Change the color in one place and use any opacity level anywhere in your CSS.
- Get the RGB values from any hex code using the converter above.
Table of Contents
If you store a hex color directly as a CSS custom property, you cannot add opacity to it without a separate variable or color-mix(). The workaround used in most professional design systems: store the three RGB channel numbers, not the hex string. Then combine them with rgba() wherever you need them.
This pattern — sometimes called the "RGB channel variable" approach — lets you define a color once and use it at any opacity level across your stylesheet. Use the converter above to get the channel values from your hex code.
Why Storing Hex Directly in CSS Variables Limits Opacity
If you define --brand: #3B82F6 and try rgba(var(--brand), 0.5), browsers reject it. The rgba() function expects three separate numbers, not a hex string.
You end up needing separate variables for every opacity level — --brand-10, --brand-25, --brand-50 — which becomes hard to maintain as the palette grows. The channel variable pattern solves this.
Setting Up the RGB Channel Variable Pattern
Convert your hex color to RGB using the converter — for example, #3B82F6 gives you 59, 130, 246. Store those three numbers as the variable value:
:root {
--brand-rgb: 59, 130, 246;
--gray-rgb: 107, 114, 128;
--red-rgb: 220, 38, 38;
}
Now use them anywhere with any alpha value:
.overlay { background: rgba(var(--brand-rgb), 0.6); }
.badge { background: rgba(var(--brand-rgb), 0.12); }
.btn:hover { background: rgba(var(--brand-rgb), 0.85); }
.alert { background: rgba(var(--red-rgb), 0.1); border-color: rgba(var(--red-rgb), 0.4); }
Update the three numbers in one place and every opacity variant updates automatically.
Sell Custom Apparel — We Handle Printing & Free ShippingUsing the Same Variable for Solid Colors Too
Use alpha 1 to get the fully opaque version from the same variable:
.btn-primary { background: rgba(var(--brand-rgb), 1); }
Or define a companion shorthand for readability:
:root {
--brand-rgb: 59, 130, 246;
--brand: rgb(var(--brand-rgb));
}
.btn-primary { background: var(--brand); }
.btn-ghost { color: var(--brand); border-color: rgba(var(--brand-rgb), 0.4); }
This gives you both the solid color and the flexible opacity pattern from a single source of truth.
Tailwind and the Modern color-mix() Alternative
Tailwind 3 uses the same channel variable pattern internally — that is what powers its slash opacity syntax (bg-blue-500/50). Each color in the Tailwind palette is stored as RGB channels in CSS custom properties.
For projects targeting Chrome 111+, Firefox 113+, and Safari 16.2+, the newer color-mix() function achieves the same result without channel variables:
.overlay {
background: color-mix(in srgb, #3B82F6 50%, transparent);
}
Both approaches are valid. The channel variable pattern has broader browser support; color-mix() is simpler but newer.
Get Your Channel Values
Paste your hex code above to get the three RGB numbers for your CSS custom property.
Open Hex to RGB ConverterFrequently Asked Questions
Can I store a hex string directly in a CSS variable and use it with opacity?
Not with rgba(). You can use color-mix(in srgb, var(--brand) 50%, transparent) if your browser support allows it. For broader support, store the three RGB channel numbers as the variable value instead.
Does this pattern work in older browsers?
CSS custom properties work in all browsers since 2016, and rgba() has been supported since 2010. The channel variable pattern works everywhere that supports custom properties.
How do I get the three RGB numbers from my hex color?
Paste your hex code into the converter above. It shows the R, G, and B values immediately. Copy those three comma-separated numbers into your CSS variable value.
What is the CSS Color Level 4 alternative to this pattern?
Modern CSS accepts hex colors in the rgb() function directly: rgb(from #3B82F6 r g b). This relative color syntax is supported in Chrome 119+, Safari 16.4+, and Firefox 128+. It is the long-term replacement for channel variables, but the rgba pattern remains more broadly compatible today.

