Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

variable colors with <alpha-value> not working with theme function on plugins #9143

Closed
gsmeira opened this issue Aug 19, 2022 · 38 comments
Closed
Assignees

Comments

@gsmeira
Copy link

gsmeira commented Aug 19, 2022

I'm trying to create a plugin for Tailwind 3.1.8, but when I use variables on colors with the new syntax - rgb(var(--primary) / <alpha-value>) - the color stop working.

I created an example on https://play.tailwindcss.com/2apCJBfHdC

Removing the / <alpha-value> from the color value make things work again.

I'm doing something wrong?

@thecrypticace thecrypticace self-assigned this Aug 19, 2022
@Kosai106
Copy link
Contributor

Kosai106 commented Aug 27, 2022

Looks like a PR was opened about this in the past but somehow the behaviour isn't working anymore.
#8652

Related, it would be nice to be able to overwrite the <alpha-value> when using theme(), which I don't believe is possible currently. Looks like that is possible. #9008

@Kosai106
Copy link
Contributor

I hate to be the one doing this but is there any updates on this @thecrypticace?

@thecrypticace
Copy link
Contributor

No worries! Sorry for the late reply. We have been thinking this through some but other things took priority for the v3.2 release.

The reason it doesn't work for plugins like this is two fold:

  1. addUtilities doesn't do anything fancy like parsing data types. It's basically to put pure CSS into the stylesheet whenever a utility is used (and it can handle variants ofc)
  2. matchUtilities does parse data types and it takes a type option that lists all acceptable "types" for a plugin — as well as a list of values. You get the <alpha-value> behavior for "free" when using it and your type list includes color.

For example, this works today: https://play.tailwindcss.com/1a6LIjNR2S?file=config — Except for the DEFAULT case + opacity modifier which I believe is a bug but I'll have to check on that. However, we're also thinking through what we want to work here.

I think that in an ideal world each plugin would take in the opacity and modify the color itself (or we provide a function to do this for you — not sure though). And we could remove this special case for the color type. We're going to try to dedicate some time soon-ish to figuring out how this should work at a high level for plugin authors to see if:

  1. The existing matchUtilities API / workaround is what we want; OR
  2. If there's a better, more automatic API that we can design and implement.

@thecrypticace thecrypticace removed their assignment Dec 7, 2022
@Jakeduncan00

This comment was marked as spam.

@Siumauricio
Copy link

In the Library that I've created which is RippleUI, I encountered with this same issue, I created a function to apply the opacity and then when some color is called, the function will trigger and if the user specifies a opacity will go there

Definition of variables in this example
https://github.com/Siumauricio/rippleui/blob/main/config/theme/var-theme.ts#L12

The function when a user call some color
https://github.com/Siumauricio/rippleui/blob/main/config/utils/applyOpacityValue.ts#L1

@timkley
Copy link
Contributor

timkley commented Feb 14, 2023

@thecrypticace

hey 👋

I was trying to add a matchUtilities function today to automatically create some utilities from a user-defined set of colors.

I'm using this configuration as explained by you above, but can't seem to get it working like in your example:

plugin(({ matchUtilities, theme }) => {
  matchUtilities(
    {
      foo: (value) => ({ backgroundColor: value }),
    },
    {
      type: ['color'],
      values: theme('colors')
    }
  )
})

The generated CSS looks like this:

background-color: ({ opacityValue =1 })=>oldValue.replace("<alpha-value>", opacityValue) !important;

I tried to rename the property from backgroundColor to color which resulted in the same result.
Trying to call value as a function (value()) seems to kinda work, but results in the following error: TypeError: Cannot read property 'opacityValue' of undefined

I'm using Tailwind CSS v3.2.6.

Can you point me in the right direction?

@karimhossenbux
Copy link

karimhossenbux commented Apr 2, 2023

It's not working on the class either:
https://play.tailwindcss.com/qLbGj1TFv7

We can't apply opacity when using var(--something)

edit: workaround is to apply alpha with hex color: #00000080 for 50% i.e.

@thecrypticace
Copy link
Contributor

@karimhossenbux The reason you can't apply an opacity to var(--something) is because the colorspace is defined at runtime. What you want is to say bg-[rgba(var(--something))] and not bg-[var(--something)]. Only the 2nd of which can be written in the shorthand bg-[--something].

Until very very recently there has been no way in browsers to augment any arbitrary color and give it an alpha channel.

The only two ways to do this are:

  1. Using color-mix() to mix a color with transparent — which multiplies the alpha value.
  2. Relative color syntax which can replace a color's alpha channel. You have to make sure to use a color space with a wide gamut in case the source color is also a wide gamut color.

And, unfortunately — at least as of right now — none of those are 100% implemented across all browsers — though I think things have gotten close-ish in just the past 3ish months. Can I Use unfortunately doesn't have up-to-date data at the moment.

@re2005
Copy link

re2005 commented Apr 11, 2023

Same issue here.

Extending the theme colors won't work.

module.exports = {
    darkMode: 'class',
    content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
    theme: {
        extend: {
            colors: {
                'my-blue': 'rgb(var(--my-color-black) / <alpha-value>)',
            },
        },
    },
    plugins: [],
};

@KrisCoulson
Copy link

KrisCoulson commented May 1, 2023

var(--my-color-black) / <alpha-value>

Just wanted to comment also experiencing the same problem as re2005 extending the theme alpha-value is not being parsed properly.

As the docs suggest it should work in the CSS variables section
https://tailwindcss.com/docs/customizing-colors#using-css-variables

@austinm911
Copy link

This works for me. It was covered in the opacity section of this video https://www.youtube.com/watch?v=MAtaT8BZEAo

It seems like the docs don't mention this anywhere?

https://play.tailwindcss.com/oYulJ30B14?file=config

@re2005
Copy link

re2005 commented May 22, 2023

Hey @austinm911 thanks for the example, the problem is that we are trying to set alpha on custom colors.

@re2005
Copy link

re2005 commented May 22, 2023

After little more investigation was very clear how to make it work.

First you need to declare your color variable using RGB and not HEX

On your css config:

$blue: 56, 114, 221;

@layer base {
    :root {
        --my-color-blue: #{$blue};
    }
}

On tailwind config

module.exports = {
    theme: {
        extend: {
            colors: {
                'my-color-blue': 'rgb(var(--my-color-blue), <alpha-value>)',
            },
        },
    },
    plugins: [],
};

Usage:

<div class="bg-my-color-blue bg-opacity-20">
    Bingo!
</div>

@robdekort
Copy link

Something that might be valuable. I’ve found that theme('colors.primary.DEFAULT / 1') still works when configuring Tailwind Typography variables, but not JS based custom plugin configurations. If anyone found a workaround I’d love to learn.

@kydner
Copy link

kydner commented Aug 11, 2023

Same issues, extend color cannot use opacity. ex bg-primary/20 or bg-primary bg-opacity-20. its not work

@stefanprobst
Copy link

interestingly, theme(), "theme()" and @apply will all generate different values:

see https://play.tailwindcss.com/fX0CEoXvGu

addUtilities({
  '.test': {
    color: theme('colors.primary.DEFAULT'),
    background: 'theme("colors.primary.DEFAULT")',
    '@apply border-primary': '',
  },
})

will generate:

.test {
    color: rgb(var(--primary) / <alpha-value>);
    background: rgb(var(--primary) / 1);
    --tw-border-opacity: 1;
    border-color: rgb(var(--primary) / var(--tw-border-opacity));
}

looks like only @apply does the correct thing currently?

@robdekort
Copy link

@stefanprobst Wow, @apply in the TW config file does actually work. 🤯 Should it though? Thanks for the tip btw!

@Pagebakers
Copy link

The docs for HSL are incorrect

  // Using modern `hsl`
      primary: 'hsl(var(--color-primary) / <alpha-value>)',
      secondary: 'hsl(var(--color-secondary) / <alpha-value>)',

should be

  // Using modern `hsl`
      primary: 'hsl(var(--color-primary), <alpha-value>)',
      secondary: 'hsl(var(--color-secondary), <alpha-value>)',

@thecrypticace
Copy link
Contributor

@Pagebakers that is incorrect. The example is using the correct "modern" CSS syntax.

See example here: https://play.tailwindcss.com/rFbKXTknA2
And the CSS spec: https://www.w3.org/TR/css-color-4/#the-hsl-notation

@kobe-f8
Copy link

kobe-f8 commented Nov 15, 2023

I've stumbled on the same problem in my current project, I've defined some theme colors:
white: 'oklch(100% 0 0 / <alpha-value>)'

And when I reference these colors to attach them to a css variable like so:
'--color-theme-contrast': theme('colors.white')

It get's outputted like so in the css:
--color-theme-contrast: oklch(100% 0 0 / <alpha-value>);

Very frustrating because my current project depends on those css variables, otherwise i'm stuck for the foreseeable future. It would be nice if I could just target the actual value of the color, so that it just outputs 100% 0 0

@mominshaikhdevs
Copy link

this issue has been open for more than half and a year now. when will this issue be fixed?

@safwanolaimat
Copy link

This a working version of your example

https://play.tailwindcss.com/e0JLQ1XNqB

@marcorieser
Copy link

colors: {
  primary: 'rgb(var(--color-primary) / <alpha-value>)',
}

So using "theme('colors.primary')" instead of theme('colors.primary') seems to do the trick. Nice 👍

@enzocomics
Copy link

enzocomics commented Dec 16, 2023

interestingly, theme(), "theme()" and @apply will all generate different values:

see https://play.tailwindcss.com/fX0CEoXvGu

addUtilities({
  '.test': {
    color: theme('colors.primary.DEFAULT'),
    background: 'theme("colors.primary.DEFAULT")',
    '@apply border-primary': '',
  },
})

will generate:

.test {
    color: rgb(var(--primary) / <alpha-value>);
    background: rgb(var(--primary) / 1);
    --tw-border-opacity: 1;
    border-color: rgb(var(--primary) / var(--tw-border-opacity));
}

looks like only @apply does the correct thing currently?

I ran into this issue today and this is fixed it for me. Thanks so much @stefanprobst !

@Sandros94
Copy link

Anyone was able to create a workaround when dealing with hex vars?

@crswll
Copy link

crswll commented Jan 5, 2024

You can use hex or any color format you want if you use color-mix.

colors: {
  primary: `color-mix(
    in srgb,
    var(--primary-color-in-hex),
    transparent calc(100% - 100% * <alpha-value>)
  )`
}

You can make it much less wordy with a simple function like:

const colorMixAlphaValueWithCustomProperty = customPropertyName => `color-mix(
  in srgb,
  var(${customPropertyName}),
  transparent calc(100% - 100% * <alpha-value>)
)`

/*
colors: {
  primary: colorMixAlphaValueWithCustomProperty('--primary-color-in-hex')
  secondary: colorMixAlphaValueWithCustomProperty('--secondary-color-in-hex')
}
*/

A sample play: https://play.tailwindcss.com/PLN66o7PtF?file=config

@Sandros94
Copy link

@crswll thank you very much, but I just realized it was even simpler and decided to open up a PR for a doc example:

// tailwind.config.js
module.exports = {
  theme: {
    colors: {
      // For --color-primary: #ff73b3
      primary: 'rgb(from var(--color-primary) r g b / <alpha-value>)',
    }
  }
}

@crswll
Copy link

crswll commented Jan 5, 2024

No problem. The browser support for Firefox is not there for that, though.

@Sandros94
Copy link

No problem. The browser support for Firefox is not there for that, though.

do you have a link to share? I was looking for it right now

@crswll
Copy link

crswll commented Jan 5, 2024

https://caniuse.com/css-relative-colors

@mordechaim
Copy link

@thecrypticace @crswll color-mix() seems to be supported in all major browsers. It's now completely safe to update the docs to include this.

In fact, this project of mine successfully uses this approach.

@reinink
Copy link
Member

reinink commented Feb 15, 2024

Hey folks! Looking at this issue today which has been open for quite a while and thought I would share what's possible today with Tailwind CSS v3.x and also what we're hoping to support in the upcoming v4.0 release.

Reading through this issue it appears there are two different things being discussed: 1) how to add color opacity modifier support when authoring plugins, and 2) how to define colors using CSS variables while still being able to use the color opacity modifier. I will address these separately below:

Writing plugins

The original reason this issue was open was because @gsmeira was trying to write a Tailwind plugin that could have a color opacity modifier. As @thecrypticace mentioned (#9143 (comment)), this is not possible using the addUtilities function. However, you can do this using the matchUtilities function, like this:

let plugin = require('tailwindcss/plugin')

plugin(function ({ matchUtilities }) {
  matchUtilities(
    {
      foo: (value) => ({ color: value }),
    },
    {
      type: ['color'],
      values: {
        red: '#ff0000',
        green: '#00ff00',
        blue: '#0000ff',
      },
    }
  )
})

The only limitation with this approach is that you cannot create a root-level utility that supports the color opacity modifier — something like foo/50. This is unlikely to change in Tailwind CSS v3.x, however we're busy working on v4.0 and hope to support this in that version.

Using CSS variables

In addition to writing plugins, it appears that a bunch of people in this thread are also struggling with how to use the color opacity modifier when they are defining their colors using CSS variables. Something like this:

// tailwind.config.js
export default {
  theme: {
    extend: {
      colors: {
        primary: 'var(--my-primary-color)'
      }
    },
  },
  plugins: [],
}

While this works as a simple color utility (eg. text-primary), it doesn't work when you try to use the color opacity modifier (eg. text-primary/50).

Our documentation does explain how to do this (see here), however this assumes that you're using rgb colors. If you're using hex, oklch, or other color formats you need to get a little more creative with how you implement this.

Let's say you have the following CSS variables defined in your project:

html {
  --my-hex-color: #ff0000;
  --my-oklch-color: oklch(63.24% 0.286 29);
  --my-named-color: red;
}

Here is how you can use the color-mix() function in CSS to make all of these colors work in Tailwind with the color opacity modifier:

// tailwind.config.js
export default {
  theme: {
    extend: {
      colors: {
        hex: 'color-mix(in srgb, var(--my-hex-color) calc(<alpha-value> * 100%), transparent)',
        oklch: 'color-mix(in srgb, var(--my-oklch-color) calc(<alpha-value> * 100%), transparent)',
        named: 'color-mix(in srgb, var(--my-named-color) calc(<alpha-value> * 100%), transparent)',
      }
    },
  },
  plugins: [],
}

With that all in place you can now use text-hex, text-hex/50, text-oklch, text-oklch/50, text-named, text-named/50, etc.

Here is a Tailwind Play demoing this: https://play.tailwindcss.com/LJMZg2LLta


Really hope that helps! Going to close this issue for now as there are workarounds available in the current version of Tailwind, and it's something we plan to change in v4.0 🤙

@reinink reinink closed this as completed Feb 15, 2024
@reinink reinink self-assigned this Feb 15, 2024
@rob-baker
Copy link

Hi, just moved across to tailwind/daisyui and think I have the same issue. I need to support older browsers/devices (chrome 106/Android 6).

Is there a fix for this?

@reinink
Copy link
Member

reinink commented Feb 16, 2024

@rob-baker what specifically isn't working in your project? Can you share a minimum reproduction?

@rob-baker
Copy link

rob-baker commented Feb 16, 2024

Thanks for the quick response. I may of raised this in the wrong place!
using:

nuxt: 3.9.3
tailwindcss: 3.4.1
autoprefixer: 10.4.17
daisyui: 4.6.0

Background colours are not working on older devices, I defined a theme in tailwind.config.js:


export default {
...
    daisyui: {
    themes: true, 
    base: true,
    themes: [{
    hstheme: {
        "primary": "#6b21a8",         
        "secondary": "#22ee00",                 
        "accent": "#be123c",                 
        "neutral": "#f87171",                 
        "base-100": "#171c26",
        "info": "#06b6d4",                 
        "success": "#22c55e",                 
        "warning": "#fde68a",
        "error": "#f87171",
        },
      },
      'dark',
      'light'
  ],

I don't think the older browsers support "oklch" colors.

Static Site:
https://www.pathuku.com/games/

@kg-currenxie
Copy link

It works well for me, with re-using tailwind classes in my custom ones:

/** @type {import('tailwindcss').Config} */

// Support custom colors like `bg-surface/50`
// https://github.com/tailwindlabs/tailwindcss/issues/9143#issuecomment-1946755547
function toRgba(variableName) {
  return ({ opacityValue }) => {
    return `color-mix(in srgb, var(${variableName}) calc(${opacityValue} * 100%), transparent)`
  }
}

module.exports = {
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx}',
    './src/components/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      colors: {
        surface: toRgba('--color-surface'),
        'primary-on-surface': toRgba('--color-primary-on-surface'),
        'primary-on-bg': toRgba('--color-primary-on-bg'),
        'warning-on-surface': toRgba('--color-warning-on-surface'),
        'warning-on-bg': toRgba('--color-warning-on-bg'),
      },
    },
  },
  plugins: [],
}

css file:

/* Themes */
:root {
  --color-surface: #fff;
  --color-primary-on-surface: theme('colors.gray.500');
  --color-primary-on-bg: theme('colors.gray.950');
  --color-warning-on-surface: theme('colors.orange.500');
  --color-warning-on-bg: theme('colors.orange.600');
}

.theme-dark {
  --color-surface: #2b202c;
  --color-primary-on-surface: theme('colors.gray.50');
  --color-primary-on-bg: theme('colors.gray.50');
  --color-warning-on-surface: theme('colors.orange.400');
  --color-warning-on-bg: theme('colors.orange.500');
}

@sos0
Copy link

sos0 commented Apr 5, 2024

I don't think the older browsers support "oklch" colors.

@rob-baker FWIW:
Here's the compatibility information from Mozilla documentation
image

And relative usage data from caniuse
image

@ankurpowar
Copy link

It works for me only if I use the legacy format (rgba) as prescribed in official docs.
i.e.

// Using legacy rgba

primary: 'rgba(var(--color-primary), <alpha-value>)',
secondary: 'rgba(var(--color-secondary), <alpha-value>)',

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests