postcss / postcss-custom-properties

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

implementation idea for cascading variables #115

Closed Nemo64 closed 6 years ago

Nemo64 commented 6 years ago

So, I just had this idea on how cascading variables might be implementable. It would look like this:

.element--red {
    --color: red;
}
.element {
    background-color: var(--color);
}

/* becomes */

.element--red { /* may still contain the var definition based on settings */ }

.element { /* may still contain the property based on fallback etc. */ }

.element--red.element,
.element--red .element {
    background-color: red;
}

Now I know that this has a lot of issues. Selector merging isn't always straight forward and there are also priority rules so this isn't fool proof. Property definitions may need to be limited to classes to save a lot of headaches.

And it becomes really complicated if more than 1 variable is used within one property. A gradient like background-image: linear-gradient(var(--color1), var(--color2)); might need a lot more than 1 rule based on how often the custom-properties are defined. Basically every possible combination must be defined.

But even with those caveats and if i'm not overlooking something big here, this would allow one to use custom properties to the full extend. Which would be awesome.

So what am i overlooking? 🤔

Nemo64 commented 6 years ago

Here is a more complicated case:

.color {
    --color: red;
}

.nav-item  .nav-link {
    background-color: var(--color);
}

/* becomes */

.color .nav-item  .nav-link,
.color.nav-item .nav-link,
.nav-item .color .nav-link,
.nav-item .color.nav-link {
    background-color: red;
}

And while writing this i noticed this problem:

div {
    background-color: var(--color);
}

.color div { /* this has a higher priority as "div" */
    background-color: red;
}

div { /* so this wouldn't override the color since the priority of a type selector is lower */
    background-color: blue;
}

But this would work again:

[attr] {
    background-color: var(--color);
}

.color [attr] { /* attribute selectors have a higher priority than class selectors so this inherits that priority */
    background-color: red;
}

[att] { /* this still has the priority of an attribute selector */
    background-color: blue;
}

So as far as i know, the priority order is

  1. universal selector
  2. type selector
  3. class selector
  4. ... everything else

So by limiting the the property definition to classes, it would only do problems if you override a 1:1 rule like overwriting div with div since any more specific rule has a higher priority, ergo at least the same priority as the class selector...

jonathantneal commented 6 years ago

I would not want to enter into presuming the DOM order, which matters more than selector weight.

I am open to supporting html per #100

Nemo64 commented 6 years ago

Did you understand my proposal? I did nowhere presume the dom order, i just merged css selectors so that the browser can do the heavy lifting.

this is what I want to be able to do: https://jsfiddle.net/69sbvpqn/6/ and this is the css I want to create: https://jsfiddle.net/7wbg85yd/

jonathantneal commented 6 years ago

Hey @Nemo64, while I thought I did, I’m open to the idea that I did not understand your proposal, and so I will review it again.

jonathantneal commented 6 years ago

After reviewing the pitch, again, I would be open to a PR, but it sounds like an incredible undertaking. However, solving this issue would also allow :matches to be more-correctly polyfilled :)

Nemo64 commented 6 years ago

I'm not sure what :matches has to do with it.

However, I noticed that I overlooked a pretty obvious case that this implementation can't resolve. https://jsfiddle.net/xds26yam/ https://jsfiddle.net/wo7Lk2tn/ The browser just looks at selector order while css properties are inherited from the first parent that has them defined. I'd need a way to increase selector priority based on the distance to the parent https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity#tree-proximity-ignorance. I don't think I could live with that limitation besides the other limitations I already mentioned.

Therefor I probably give up on it unless I get I bright Idea on how to overcome that.

jonathantneal commented 6 years ago

I understand, @Nemo64. Thanks for looking into this.