w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.44k stars 657 forks source link

[css-contain-3] Make `<container-query>` optional in `@container` #9192

Open LeaVerou opened 1 year ago

LeaVerou commented 1 year ago

Edit: The rationale below is wrong, but the proposal still stands, see https://github.com/w3c/csswg-drafts/issues/9192#issuecomment-1679443058


While we have a resolution in https://github.com/w3c/csswg-drafts/issues/7858 to add a function for every container query unit that allow to reference a named container, there is a much more lightweight way that can be implemented right away to make these use cases a little less annoying: making the <query> part of container queries optional.

This is real code I had to write yesterday:

@container word-card (width < 100vw) {
    height: min(100cqw / var(--total-aspect-ratio), 40vh);
}

The entire reason this container query exists, is to allow me to use cqw units for that particular named container. The (width < 100vw) query is only there because omitting it would render the rule invalid, as the spec makes this part mandatory.

<container-condition> = [ <container-name> ]? <container-query>

Can we just make it optional?

If we’re fine with allowing entirely bare @container {} rules, the change could be as simple as:

<container-condition> = [ <container-name> ]? <container-query>?

if we want at least name OR condition, it would be:

<container-condition> = [ <container-name>? <container-query>? ]!
Loirooriol commented 1 year ago

Note that if you want the condition to be true, width >= 0 is safer than width < 100vw.

Still, the problem with this proposal is that cq units are not tied to the container query, so even if using @container word-card, they can resolve against a different container:

<!DOCTYPE html>
<style>
@container foo (width >= 0) {
  #target {
    width: 100cqw;
    height: 100cqw;
    background: yellow
  }
}
</style>
<div style="width: 200px; border: solid cyan; container: foo / inline-size; --total-aspect-ratio: 1">
  <div style="width: 100px; border: solid magenta; container: bar / inline-size">
    <div id="target"></div>
  </div>
</div>

The idea is that cqw(foo) would allow

LeaVerou commented 1 year ago

Still, the problem with this proposal is that cq units are not tied to the container query, so even if using @container word-card, they can resolve against a different container:

I was not proposing this as an alternative, just as a quick win to make the current situation less painful until cqw() and friends can be implemented. And because if @container name is useful by itself, it should be allowed.

Loirooriol commented 1 year ago

What I tried to explain above is that I don't see how the proposal actually improves this problem. It seems based on a misunderstanding of how cq units resolve. To be clearer,

@container word-card {
  #target { height: min(100cqw / var(--total-aspect-ratio), 40vh); }
}

will resolve the cq units just like

#target { height: min(100cqw / var(--total-aspect-ratio), 40vh); }

Allowing @container word-card {} might still be useful to apply styles with the condition that some ancestor has container-name: word-card, but won't improve cq units.

LeaVerou commented 1 year ago

@Loirooriol you are totally right. I'm not sure how in the use case that prompted this I got a different result. I've edited the first post to link to your comment, since I still think making the query part optional would have some (limited) utility.

mirisuzanne commented 1 year ago

I agree there are likely use-cases for name-only queries, and it would be great to support this.

css-meeting-bot commented 10 months ago

The CSS Working Group just discussed [css-contain-3] Make `<container-query>` optional in `@container`, and agreed to the following:

The full IRC log of that discussion <dael> oriol: I can try to explain, though maybe leaverou would prefer to be in discussion
<dael> astearns: Why don't you introduce
<dael> oriol: In this issue when you have a container @rule there's container-query. Idea is make it optional. leaverou prop as a way to have more reasonable defaults for container-query units.
<dael> oriol: That wouldn't be possible, but still prop to make it optional. Functionality it would have is to apply styles with the assumption that a container has a given ancestors name, but not giving a condition. I think it's reasonable. not sure super useful, but reasonable and not hard to impl
<dael> oriol: Idea is allow to provide a name but with no condition in the element
<dael> TabAtkins: How do you conditionalize styles to only apply if ancestor has container?
<dael> fantasai: Using @concerner container anme {}
<dael> oriol: The idea is provide the name with no condition. The condition would be there is an ancestor with the name
<dael> TabAtkins: Got it. That seems reasonable
<dael> astearns: Is this possible by setting condition to something that always evaluates to true
<dael> TabAtkins: Yep. And that seems silly to require
<dael> astearns: Yep, if this exists already and we're making it easer it's good
<dael> astearns: Prop: @container rule can have just a container name and match the closest container with that name
<dael> astearns: Obj?
<dael> RESOLVED: @container rule can have just a container name and match the closest container with that name