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

[css-nesting] Allow custom property within nested at-rule conditions #8753

Closed
miragecraft opened this issue Apr 22, 2023 · 7 comments
Closed

Comments

@miragecraft
Copy link

miragecraft commented Apr 22, 2023

I believe the rationale against allowing custom properties was because custom properties are applied against elements, not at-rules that aren't attached to any element.

But now that we can nest at-rules inside selectors, shouldn't we then allow custom properties for nested at-rule conditions?

As for why we can't just use the proposed author env() variable, it's because we can't dynamically change it per element.

Example of a Flexbox component with dynamic breakpoint set via inline style (which is not possible with env()):

.flex {
  display: flex;
  container-type: inline-size;
  --breakpoint: initial; /* reset */
}
.flex > * {
  flex: 1;
  @container (calc($(--breakpoint) < width)) {
    flex-basis:100%;
  }
}
<div class="flex" style="--breakpoint:640px">
  <div>column</div>
  <div>column</div>
</div>
@miragecraft miragecraft changed the title [css-nesting] Allow custom property within nested @media condition [css-nesting] Allow custom property within nested at-rule conditions Apr 22, 2023
@Loirooriol
Copy link
Contributor

I don't follow your reasoning, I don't see why nesting should imply any change.

Anyways, in #8088 we already resolved to allow var() in container queries (regardless of nesting).

@miragecraft
Copy link
Author

Thanks for the heads up, somehow I missed that one in my searches.

@tabatkins
Copy link
Member

For @container, there's a context to draw from (the container element, which is a single specific element when evaluating a CQ against an element). For @media this is still not the case; in .foo { --x: 100px; @media (min-width: var(--x)) {...}}, we have no idea what element the --x should be drawn from. There can be multiple elements matching .foo, and other rules might have higher-specificity properties overriding the --x you see there, giving each of them different values for it.

@miragecraft
Copy link
Author

miragecraft commented Apr 25, 2023

I'm not sure I understand the distinction.

You say that for @container, there's a context to draw from which is the container element, that's a single specific element when evaluating a CQ.

However, you must define the container element using the very same selector .foo that you consider problematic when it comes to @media.

.foo { --x: 100px; container-type: inline-block; @container (min-width: var(--x)) {...}}

So you can also override --x from somewhere else, such as

.foo {--x: 200px!important} or .foo.foo {--x:200px}.

How does @media differ from @container when they face the same issue?

Also I don't think it's actually a problem that the variable --x can be over-ridden from other sources, I consider it a feature not a bug.

If you want to treat --x as a constant then either add !important to it or impose rules upon yourself to not declare it , somewhere else, such as follow a naming convention and rename --x to --_foo-breakpoint etc.

@Loirooriol
Copy link
Contributor

It's not a matter of being able to change --x, it's a matter of having a reasonable and well-defined element from which we can retrieve the value of --x.

The difference is that @container checks a condition on elements (so we can take --x from the current candidate), while @media doesn't really do anything with elements.

@miragecraft
Copy link
Author

miragecraft commented Apr 25, 2023

I think I see what you're saying.

To confirm, because @container inherently need to check the element marked as the container, the code/logic is already there to allow it to check the --x custom property while it's already looking up the element anyways.

However @media in its current incarnation never checks any element, so it would mean completely rewrite the code/logic if we allow it to accept --x custom property when it is nested.

Is that correct?

Edit: I can also see a problem where the --x is changed within the nested @media leading to possible infinite loop scenario, which @container sidesteps because you can't alter the parent, only the children.

@tabatkins
Copy link
Member

Right, in @container (width > 50px), we're checking the width of one element - the container. This one element can vary while styling different elements (that is, in @container ... { .foo { color: red; }}, the .foo elements can each be querying a different container element), but for any given element, there is exactly one, well-defined, element being queried. Checking the value of a custom property on that container element is essentially identical to checkings its size.

In @media ... { .foo {color: red;}}, no element is referenced at all for the MQ. It checks the document itself for all its queries. So there's nothing to draw from.

And we can't change the behavior when nesting, either: in .bar { @media ... { .foo { color: red; }}}, we couldn't say that @media can reference the .bar element to draw values from, because... which .bar element? Nesting imposes absolutely no relationship between the .bar selector and the .foo selector; it's purely a syntax convenience letting you write shorter selectors in common situations. The .bar might be an ancestor, a descendant, a previous or following sibling, or something completely unrelated like in .bar { .foo:not(&) {...}}; there might be multiple .bar elements with the given relationship and no way to indicate which one you mean...

Finally, MQs are defined to be either true or false at the rule level, and this is reflected in the APIs that use them. If they start imposing truth or falsity on individual contained rules (like @container effectively does), instead, that's a major change, and fairly incompatible with how things currently work.

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

3 participants