Skip to content
This repository has been archived by the owner on Aug 22, 2023. It is now read-only.

Support CSS variables inheritance #63

Closed
hteumeuleu opened this issue May 21, 2014 · 8 comments
Closed

Support CSS variables inheritance #63

hteumeuleu opened this issue May 21, 2014 · 8 comments

Comments

@hteumeuleu
Copy link

Current version 1.0.3 doesn't support CSS variables inheritance. So if we take the following HTML and CSS code :

<div class="block">
    Root Block
</div>
<div class="sidebar">
    <div class="block">
        Sidebar Block
    </div>
</div>
:root {
    --large:10px;
}

.sidebar {
    --large:20px;
}

.block {
    padding:var(--large);
}

The expected output should be something like this :

.block {
    padding:10px;
}

.sidebar .block {
    padding:20px;
}

This way we respect CSS inheritance, but this may create other issues as it creates more specificity.

@MoOx
Copy link
Contributor

MoOx commented May 21, 2014

This issue has already been discussed on rework-vars and (for now) limitation is explained here https://github.com/reworkcss/rework-vars#what-to-expect

@hteumeuleu
Copy link
Author

Ah, ok, merci.
Maybe the main site "marketing" speech should be changed then. Because this is clearly not like a CSS polyfill then, and it's quite misleading.

@kasperisager
Copy link

Bummer, variable inheritance was one of the things I was personally really looking forward to after having read the W3 spec 😕

@MoOx
Copy link
Contributor

MoOx commented Jun 21, 2014

We are using dynamic variables syntax to create a classic (preprocessed) variable implementation but we can't handle that since we can't guess the dom tree, so we can make relevant results.
That's why rework-vars is limited to :root definition.

That being said, I guess we can make this clear. I'll try to make this clear on the doc & on the website.

The best we can probably do is to handle #58

@MoOx MoOx added the need doc label Jun 21, 2014
@yarray
Copy link

yarray commented Dec 2, 2014

@MoOx I'm trying to understand your explanation by constructing cases:

Change css file provided by @hteumeuleu to:

:root {
    --large:10px;
}

.sidebar {
    --large:20px;
}

div .block {
    padding:var(--large);
}

According to the specification, the output should be (all cases should be covered since we cannot guess the dom):

.block {
    padding:10px;
}

div.sidebar .block {
    padding:20px;
}

.sidebar div .block {
    padding:20px;
}

div .sidebar .block {
    padding:20px;
}

Since rules in real world css are much more complex, the generated css file will be quickly bloated.

However,

scoped variables are really nice... So, how about partial support? For example, we can interpret the scope as the topmost selector, which means the output of the changed example will be:

.block {
    padding:10px;
}

.sidebar div .block {
    padding:20px;
}

This still doesn't work for the original html (the original css works, though), but at least we can hack it:

<div class="block">
    Root Block
</div>
<div class="sidebar">
    <div>
        <div class="block">
            Sidebar Block
        </div>
    </div>
</div>

It may seem confusing at first, but it may not be that bad since the working scenario is a subset of the working scenario promised by the specification. (So after the specifications being implemented in browsers what worked will still work)

@MoOx
Copy link
Contributor

MoOx commented Dec 2, 2014

Partial support is too dangerous. Any serious project won't do that.
You can also checkout postcss/postcss-custom-properties#1 & postcss/postcss-custom-properties#9 to understand why it should not be done.
I've tried to do that for cssnext (in the postcss plugin linked above) but it's not a game I want to play anymore.

This issue should be closed but since I'm involved in another project I'll let the owners do that :)

@yarray
Copy link

yarray commented Dec 3, 2014

@MoOx Thanks for your links. Now I found what's wrong with my suggestion... The key problem is, when resolving scoped variables distances between DOM elements are critical, but it's totally unexpressible due to it's not a criteria of cascading rules.

It brings some critical problems. Suppose we have a variable x with two scoped assignments:

.a {

  --x: 0;

}

.b {

  --x: 1;

}

Then our luck depends on the rule which uses the variable, if it’s something biased like

p.a {

  <any property>: val(--x);

}

then we are lucky since it can be interpreted as a single rule:

p.a {

  <any property>: 0;

}

However, if there’s something more general, like this simple input rule:

p {

<any property>: val(--x);

}

then we are in trouble. Following will proved that we cannot use finite output rules to cover all the DOM cases:

  1. Suppose we have finite output rules which can cover all cases, which means, the selected variable value using CSS rules is unambiguous and always the same as the result of scoped evaluation.

  2. From the finite output rules, we can always find a strongest rule R to match 0, and a strongest rule R of the same strength to match 1, due to the symmetry. Notice there should reasonably no adjacent operator “>” in the rules since we cannot guess DOM.

  3. We can find DOM hierarchy which match R as well match S, also due to symmetry. we sign the DOMs without the last element p as D and E. So we get:

    R(Dp) = 0, S(Ep) = 1

    According to 1, we know that Dp ~ 0, Ep ~ 1, where ~ means “scoped evaluate to”.

  4. Consider a new DOM EDp*, then R(EDp) = 0 and S(EDp) = 1. According to 1, R and S are strongest and have the same strength, so here we cannot determine whether x in EDp should be evaluated to 0 or 1, while, though, it’s obvious that EDp ~ 0!

Seems a more formal proof is possible, but it’s already sufficient to say it’s impossible to implement such a functionality (even partially as I suggested). Really a pity… Maybe the approach taken by uncss is the only real way to go as you suggested before. The only possible “partial” implementation seems to restrict the scope to 0 or 1 levels, but that seems a bit too rough.

* Strictly speaking, EDp is not always legal, but at least it's legal for a DOM consist of only div.

@ianstormtaylor
Copy link
Contributor

Closing since it's out of scope for Myth for now.

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

No branches or pull requests

5 participants