postcss / postcss-custom-properties

Use Custom Properties in CSS
https://postcss.github.io/postcss-custom-properties
MIT License
595 stars 77 forks source link

Overriding custom properties not supported #173

Open lauriii opened 5 years ago

lauriii commented 5 years ago

According to W3C reference, custom properties can be overridden by more specific selectors.

Example:

:root {
  --color: black;
}
div {
  --color: red;
  color: var(--color);
}

Expected:

div {
  color: red;
}

Current behavior:

div {
  color: black;
}

I also created a failing test case for this.

pascalduez commented 5 years ago

Hi,

without a DOM, PostCSS can't replicate 100% of the custom properties behaviour, so it's limited to declarations on the :root element. This used to be on the Readme, but was removed apparently.

There used to be a warning (under an option) as well, but it was also removed.

Personally when I use cascading custom properties like in your example, I tend to had a fallback by hand, when it make sense.

joelpittet commented 5 years ago

Could it be simulated to at least look in the context of the block it's in or the same selector for overrides?

maddesigns commented 5 years ago

Could we (ab)use the fallback mechanism, like this:

div {
  --color: red;
  color: var(--color, red);
}

?

theseanl commented 5 years ago

I suppose one way to resolve this is to transpile

a { --prop: red; }
b { --prop: blue; }

c { color: var(--prop) }

to, assuming b has higher specificity than a,

c:matches(a *):matches(a) { color: red; }
c:matches(b *):matches(b) { color: blue; }

so if there were m rules for a custom property and n rules that use the custom property, we end up with mn rules. We can calculate the specificity of selectors, and there is another plugin that transpiles :matches (which is imperfect as well though), so this looks doable.