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] Define a syntax for style-based container queries #6396

Closed
mirisuzanne opened this issue Jun 18, 2021 · 19 comments
Closed

[css-contain-3] Define a syntax for style-based container queries #6396

mirisuzanne opened this issue Jun 18, 2021 · 19 comments

Comments

@mirisuzanne
Copy link
Contributor

Container Queries should allow us to write conditional rules based on the computed styles of an ancestor container, since, according to @andruud:

Knowing the computed style (and even layout) of the container before evaluating the container query is already needed for normal (size) queries.

I'm branching this issue off from #5989 (What container features can be queried?) and #5624 (Higher level custom properties that control multiple declarations) – to specifically discuss syntax for querying a container's computed styles as part of css-contain-3.

Several of the use-cases mentioned so far (actual syntax TBD):

  1. testing for a discrete value on a property, eg (background-color = red) or (--pill = on)
  2. testing that a custom property has any not-guaranteed-invalid value, eg (--is-small)
  3. testing range comparisons of length values, eg (50vw < 400px) or (--small > 50vw)

And some of the issues to address:

  • We need to define how discrete values are compared (is it a token sequence? how is whitespace handled? etc)
  • Custom properties used in range queries may need to be registered with @property
  • Some values (like % lengths) evaluate differently on different properties. What do they mean in a query?

I'd like to get more use-cases and issues documented here, so that we can work through them in more detail.

@andruud
Copy link
Member

andruud commented Jun 21, 2021

We can't do (background-color = red) though, right? (E.g. width is both a feature and a property).

@mirisuzanne
Copy link
Contributor Author

@andruud that's right, we have to work around features like (width = 30em), (width >= 30em), (min-width: 30em). Maybe a wrapping property() or computed() function?

@fantasai
Copy link
Collaborator

Agenda+ to add style queries. Proposal:

  • style queries use style() function; for disambiguation, size queries use size() function
  • style queries query the computed value, with the value in the query also computed wrt the query container element
  • style queries cannot query ranges (for simplicity initially, and to avoid confusion since many computed values resolve to lengths but are not comparable to lengths until after the computed value stage)
  • style queries can be combined using the boolean logic and syntax from @supports

Note: @mirisuzanne and I drafted this proposal into the ED at https://drafts.csswg.org/css-contain-3/#style-container in f209f6a

@andruud
Copy link
Member

andruud commented Sep 21, 2021

Nice.

So you opted to not have <general-enclosed> at all? Just asking since it would make e.g. size(width > 10px) or future(something) a parse error.

@mirisuzanne
Copy link
Contributor Author

@andruud We absolutely need to think through the behavior we want here for future syntax. I think we also might want to consider defaulting queries without a function to be size queries - but that likely needs conversation in the WG.

@fantasai
Copy link
Collaborator

@andruud <general-enclosed> needs to parse without invalidating the entire rule, but it's not valid syntax. If you put random stuff in there, the browser shouldn't choke on it -- but neither should your syntax checker say your style sheet has no errors.

@andruud
Copy link
Member

andruud commented Sep 29, 2021

@fantasai My point was that as currently proposed, the browser would "choke on it". 🙂

@FremyCompany
Copy link
Contributor

I am generally happy with the proposal, but was wondering:
Is attribute syntax something we could look into?

... style(width)$='%' ... {
   /* style to use if the container is percentage-sized */
}

This would allow to use custom properties that are space-separated lists of toggles, then use |= to query each token independently.

Just food for thought.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-contain-3] Define a syntax for style-based container queries, and agreed to the following:

  • RESOLVED: Accept proposal in ED. Split range syntax and attributes to new issue
The full IRC log of that discussion <dael> Topic: [css-contain-3] Define a syntax for style-based container queries
<dael> github: https://github.com//issues/6396
<fantasai> i/Topic/astearns: Resolved, unless someone comes back with a strong opinion later
<dael> miriam: style based container queries are idea we can look at container and check computed value of a property and query that and change things for desc for value of property
<dael> miriam: Mostly used for high level custom prop where have set of values, check on parent, and based on query make changes
<dael> miriam: Other use cases, that's main
<dael> miriam: fantasai and I added proposed syntax to spec.
<dael> miriam: At this point it uses normal property syntax so : between. Some issues about supporting range syntax or attribute selector syntax
<dael> astearns: Opinions?
<dael> TabAtkins: Defining equality as something we haven't done in css. Will require some work. Wait, we have equality for transition. Ignore me. On to fantasai
<astearns> ack fantasai
<astearns> s/TabAtkins.*$//
<dael> fantasai: We talked about potentially having range. Was hesitant b/c if want to catch range of values for width you would not be able to do with style query b/c can only compare length but not auto or other keyword-based width values
<smfr> q+
<dael> fantasai: Reason I didn't want to add range syntax for computed style is b/c will add confusion. Some point in future may have use cases to add but best for now to keep to equal or not
<astearns> ack smfr
<dael> fantasai: Mostly will do lengths and use container queries for things with sizes
<dael> smfr: A bit confused. Understood container queries limited to elements with certain values on contain property.
<dael> smfr: Feature here sounds like could be independant of contain property. Features here apply whe not using?
<dael> miriam: Resolved earlier to use sytax to establish containers. Then browser establishes containement behind the scenes. This would rely on container type that doesn't apply containment in background
<dael> smfr: Makes sense
<dael> astearns: Other comments?
<dael> astearns: My understanding is we're looking for resolution to accept what's in ED and leave range syntax and attributes to future issues
<dael> miriam: wfm
<dael> astearns: fremy it was your comment about attributes. Okay to ask you to open new issue?
<dael> fremy: Isn't it same issue but delay to new level? I can open a new one if people prefer
<dael> fantasai: Yes please
<fremy> fantasai: ok, will do
<dael> astearns: Prop: Accept proposal in ED. Split range syntax and attributes to new issue
<dael> RESOLVED: Accept proposal in ED. Split range syntax and attributes to new issue

@tabatkins
Copy link
Member

Yeah, @fantasai, I think you misunderstood @andruud - we need <general-enclosed> in the grammar to allow for future expansion without making the entire rule fail for older browsers, just like we do in the other conditional rule syntaxes.

In this context, I think we should use the three-value boolean that MQs does.

@mirisuzanne
Copy link
Contributor Author

@tabatkins Does this need to be re-opened and addressed?

@deanleigh
Copy link

Will style-based container queries support elements styled with data-attributes please?
I use things like this a lot where utility classes can be added programmatically in CMS UI and manipulated in the front end with JS:
data-screen-col_12="justify-content:space-between;"
Would that register as a 'style' ?

@tabatkins
Copy link
Member

No, that's just an arbitrary string as far as the browser is concerned. If you then manually apply that string to the style attribute, it will work.

@deanleigh
Copy link

deanleigh commented Dec 10, 2021

My bad explanation sorry, I am currently using them as utility classes with media queries.
So data-screen-col_12="justify-content:space-between;" is referenced in my stylesheet like so:

@media only screen and (min-width: 1600px) { .feature__menu[data-screen-col_12~="justify-content:space-between;"] { .feature-layout__group { justify-content: space-between; } }

Would the new syntax recognise the data-attribute and its value as a style?*

@contains (min-width: 1600px) and style([data-screen-col_12="justify-content:space-between;]) {
justify-content: space-between;
}

*not sure if this would be the correct syntax?

@JaneOri
Copy link

JaneOri commented Dec 10, 2021

for it to respond to your style you'd have to query the style like so:

.feature__menu {
  & .feature-layout__group {
    container-type: style;
    ...
    @container style(justify-content: space-between) {
      /* add Extra Styles that only apply when this element has justify-content set to space-between */
      ...
    }
  }
}

because your existing system is adding justify-content: space-between when the data attribute is on the parent, those Extra Styles will only[1] be there when your feature__menu element has data-screen-col_12 attribute containing justify-content:space-between;

If you need to add more styes only based on the data attribute selector though, you can add more styles the same way you're already adding justify-content: space-between and don't need a style container query.


[1] unless something else will set justify-content to space-between too

@deanleigh
Copy link

deanleigh commented Mar 27, 2022

for it to respond to your style you'd have to query the style like so:

.feature__menu {
  & .feature-layout__group {
    container-type: style;
    ...
    @container style(justify-content: space-between) {
      /* add Extra Styles that only apply when this element has justify-content set to space-between */
      ...
    }
  }
}

because your existing system is adding justify-content: space-between when the data attribute is on the parent, those Extra Styles will only[1] be there when your feature__menu element has data-screen-col_12 attribute containing justify-content:space-between;

If you need to add more styes only based on the data attribute selector though, you can add more styles the same way you're already adding justify-content: space-between and don't need a style container query.

[1] unless something else will set justify-content to space-between too

@JaneOri Finally got around to testing this but with no luck:
https://codepen.io/deanleigh/pen/YzYVGKp?editors=1000

@mirisuzanne
Copy link
Contributor Author

@deanleigh no one has implemented style container queries at this point, even in a prototype - so there's no testing to be done. But style([data-screen-col_12="justify-content:space-between;]) will not be valid or meaningful, because (as Tab said above) [data-screen-col_12="justify-content:space-between;] is not a style, it's an attribute selector that happens to have some CSS-like information inside it. That attribute can be used to select and apply a style, but the attribute itself is not a style. You can query style(justify-content:space-between) to match a container with that style applied, and you can apply that style using your attribute -- but those are two unrelated steps as far as CSS is concerned.

@deanleigh
Copy link

deanleigh commented Mar 28, 2022

Sorry @mirisuzanne I pasted as a reply to an old post where I mistakenly thought style would work like more like :where()
The codepen has my example with what I believe is the correct syntax (I feel very bad now for causing you to explain it to me again)

@mirisuzanne
Copy link
Contributor Author

no worries!

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

8 participants