Add way to change opacity for color variables alias, fills, strokes, etc

Let’s say we have color-red and background variables where background is an alias of color-red but 20% transparent. If we output to CSS we have a couple of ways.

1. Using color-mix (well supported)

 --color-red: #ff0000;
 --background: color-mix(in oklch, var(--color-red), transparent 80%);

The colorspace can be any of the supported ones by Figma (HSL, RGB, etc…). Unfortunately, the color space is mandatory in color-mix() function. Note that it works by adding a transparent color, so the result is 100% of the original color minus the transparent value. So to get a 20% red, we need to add 80% transparent.

Demo: JSFiddle - Code Playground

2. Using relative colors (less supported)

 --color-red: #ff0000;
 --background: rgb(from var(--color-red) r g b / 20%);

This is more intuitive and produces a red 20% without doing mental calc. If using different color spaces, the returned channels are different. Eg.

 --color-red: #ff0000;
 --background: oklch(from var(--color-red) l c h / 20%);

With this new function, we can also perform calculations on the channels.

 --color-red: #ff0000;
 --background: rgb(from var(--color-red) r calc(g - 50) b / 20%);

The above solutions keep the variables dynamic preventing their values from becoming fixed. If we change color-red, also background will change

There is also a third option, using HEX colors with alpha channels, which is supported everywhere but requires values to be in any RGB color space and static values, losin aliases.

5 Likes

I was just switching over a Material Design library and hit this roadblock. Material Design 3 has 5 elevation levels of surfaces, which are defined by a fill of 2 colours: the surface colour, and then a semi-transparent tint of the primary colour in a given percentage for each level of elevation. Right now it’s defined as hex values. If I try to say it’s the variables surface at 100% opacity plus primary at, say, 5% opacity, it just changes it to 100% primary with no way to adjust it.

Figma provides the CSS for the current definition using hex for the colour definitions as:

background: var(--m-3-surfaces-light-surface-1, linear-gradient(0deg, rgba(51, 92, 168, 0.05) 0%, rgba(51, 92, 168, 0.05) 100%), #FFFBFE);

The lack of an ability to set a transparency level for a color variable means I can’t use the feature fully. Instead I’ll have solid colours using variables, and any tints/mixes using hex literals.

1 Like

Definitely need this – please Figma devs :pray:

In addition to what Equinusocio shared, our team uses design tokens to express opacity as well. So to expand on the shared example, we might have something like this:

2 Likes

You can add Variable with ALPHA Color. Check this solution

That’s true, but unfortunately it doesn’t solve the problem. When you define a core palette of colours, each core token/variable will be a solid colour, such as –color-brand-10, –color-brand-20 (…) –color-brand-100. Design tokens reference these core variables in semantic tokens – let’s say your standard background colour for buttons and other interactive elements is –color-background-default, which references –color-brand-40.

If you have components like tooltips that overlay other UI elements, and you want to give them transparency, you’d ideally want to use another semantic token like –color-background-overlay, which references the same –color-brand-40 as your other token, but also adds opacity. This currently isn’t possible. Our team is using a temporary workaround by creating semantic tokens with transparency as hard values rather than as references to core variables. In the Tokens Studio plugin, you were able not only to add hard opacity values to semantic tokens, but also create opacity tokens.

…and that’s what we don’t want.

Same here… half aliases and half hard values. Not good.

1 Like

is there a workaround yet? Or a roadmap that tells when variables v2 will be released?

4 Likes

Would also love to know if we can expect v2 within the end of the year :slight_smile:

3 Likes

Would love this too! In my organisation we would need to reference our Color Primitives and specify the opacity only in the semantic layer. This is currently impossible, I need to create new variables disconnected from the primitive value to achieve this. As it is, this seems to go against the spirit of Variables, would be amazing if this could be added!

3 Likes

This will be very helpful. Hope it gets added soon

1 Like

+1 Tailwind does this very elegantly:

<p class="text-blue-600/50">The quick brown fox...</p>

You define your fully opaque colours and then make those transparent with the slash. :heart:

1 Like

Any updates?

+1 would be great to ensure better color consistency across variables. Not to mention changing color palettes and building themes would be so much easier this way

+1 we are missing a way to apply an opacity to an alias variable… when using opacity yuou are required to use hex value instead of alias

I’d use css color-mix(in srgb, var(—brand-100), transparent 50%). Does wonders :wink:

Hers is an example Source Foundation / Tailwind CSS

The other, a bit more complex, way would be to perform Brightness / Luminance calculations on the shades of gray for contrast variations. The same way Android Dynamic Colors work.

The general idea is to have a conditional for contrast and pick either shades from white to gray, or from shades of black to gray to hit the target Contrast Ratio. Previous Android versions did this by modifying solid white/black opacity, not sure how they’re doing it right now.

So, calculating Color Variables using basic HSL/HSB and Opacity transformations is one thing, but making decisions (conditionals) on Threshold Brightness / Luminance and Threshold Contrast comparison is yet another thing. Having a set of functions to derive and modify colors is just a start.

This is a feature I’m waiting since 2017.

Comparisons on color contrasts are crucial for proper Accessibility standards adoption - WCAG contrast ratios are a thing.