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-contain-3] Multiple <container-query>s with multiple containers #6876

Open
bramus opened this issue Dec 10, 2021 · 5 comments
Open

[css-contain-3] Multiple <container-query>s with multiple containers #6876

bramus opened this issue Dec 10, 2021 · 5 comments

Comments

@bramus
Copy link
Contributor

bramus commented Dec 10, 2021

The spec currently reads (emphasis mine):

Once an eligible query container has been selected for an element, each container feature in the <container-condition> is evaluated against that query container.

Applied to the example below, both conditions will be evaluated against wrapper

.wrapper {
  container-name: wrapper;
}

.wrapper > .child {
  container-name: child;
  --responsive: true;
}

@container wrapper size(inline-size > 30em) and style(--responsive = true) {
  .wrapper > .child {
    /* styles */
  }
}

What I want to have size(inline-size > 30em) be evaluated against wrapper and style(--responsive = true) against child (or any other wrapping container) ?

Would it be feasible to pursue something like the snippet below, where it's allowed to set a <container-name> for each <container-query>?

/* Evaluate size() against wrapper, and evaluate style() against child */
@container wrapper size(inline-size > 30em) and child style(--responsive = true) {
  .child {
    /* styles */
  }
}
@bramus
Copy link
Contributor Author

bramus commented Dec 10, 2021

(I've already given this some further thought, and have identified that this could have a bigger impact. To not loiter the original post, I'm posting it as a reply)

If this change were to be considered, then why not have the original example @container wrapper size(inline-size > 30em) and style(--responsive = true) also work like @container wrapper size(inline-size > 30em) and child style(--responsive = true), and thus revert that initial quote from the spec?

Would make sense with all elements being style containers by default 1. It would make these three examples below — where one is more explicit than the other about which container to target — behave in the same way:

@container size(inline-size > 30em) and style(--responsive = true) { 
  .child {
    /* styles */
  }
}

@container wrapper size(inline-size > 30em) and style(--responsive = true) { 
  .child {
    /* styles */
  }
}

@container wrapper size(inline-size > 30em) and child style(--responsive = true) { 
  .child {
    /* styles */
  }
}

Would also make a lot of sense when nesting @container rules (which isn't specced yet):

@container size(inline-size > 30em) { /* Evaluate size() against nearest size container */
  @container style(--responsive = true) { /* Evaluate style() against nearest style container, i.e. self */
    .child {
      …
    }
  }
}

To have a size() and style() container be evaluated against the same container — which was originally described — the introduction of extra parens could group both conditions:

/* As they are grouped using parens, evaluate both against wrapper */
@container wrapper (size(inline-size > 30em) and style(--responsive = true)) {
  /* styles */
}

In summary, the evaluation would always behave like this:

  • <size-query>: always evaluated against nearest size container (most likely some parent), unless specified otherwise
  • <style-query>: always evaluated against style container (i.e. self), unless specified otherwise
  • When mixing <size-query> and <style-query>, ungrouped: each container query behaves in the same way like it does individually
  • When mixing<size-query> and <style-query>, grouped: Undecided on this, but these look like potential options:
    1. The first one determines the container
    2. The <size-query> determines the container to use
    3. Authors must be explicit about it and set a <container-name>

Footnotes

  1. As read in https://github.com/w3c/csswg-drafts/issues/6393#issuecomment-988216116

@mirisuzanne
Copy link
Contributor

mirisuzanne commented Feb 4, 2022

First, to address some of the side issues:

  • Container queries work because we explicitly disallow self-queries. By insisting that the query target is always an ancestor of the selected element, we avoid potential for loops. So I think that aspect ("i.e. self") is off the table, but not required for the rest of your proposal.
  • Some of the questions here depend on (and expand on) the questions about implicit container-selection in [css-contain-3] Determine container type automatically from the query #6644. If we want implicit selection, and we want to allow multiple containers, the two need to work together.

But to focus in on the primary questions here:

1. Is it possible for one element to query multiple containers?

[updated to reference current spec language]

While we haven't written nesting in explicitly, I would expect Nested queries allow this already based on the current spec:

Style rules defined on an element inside multiple nested container queries apply when all of the wrapping container queries are true for that element.

Each @container rule would handle container-selection internally, potentially selecting different containers, and the styles would only apply if all container queries resolve true:

@container size-wrapper size(inline-size > 30em) { 
  @container style-wrapper style(--responsive = true) {
    .child { /* styles based on two different containers */ }
  }
}

Which simplifies this issue a bit more, down to just solving:

2. Do we want to allow that in a single @container rule without nesting?

I like the idea. 😁

Maybe we want to spend a little time pushing on it to make sure it really improves readability, since I don't think it adds new functionality. The other question is if it complicates implementation, or if it could be easily added in level 4?

@andruud
Copy link
Member

andruud commented Feb 7, 2022

@container wrapper size(inline-size > 30em) and child style(--responsive = true)

Would it then make sense to somehow associate the name/container-selection part with the corresponding condition in a way that's more visually obvious? E.g.

@container wrapper:size(inline-size > 30em) and child:style(--responsive = true)
@container wrapper:(size(inline-size > 30em) and style(--responsive = true))

@astearns
Copy link
Member

astearns commented Feb 9, 2022

In #6644 (comment) we resolved that a single container query will select a single container to answer all its queries

  • RESOLVED: All queries in an @container rule are against the same container, which can answer them all

@mirisuzanne
Copy link
Contributor

I'll leave this issue open for now, since it's a reasonable bit of syntax sugar to consider down the road – but it seems we're not planning to address it in css-contain-3. Maybe I'll label as deferred.

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

No branches or pull requests

5 participants