csswg-drafts icon indicating copy to clipboard operation
csswg-drafts copied to clipboard

[css-conditional] Make CSSSupportsRule expose whether its condition is met

Open SebastianZ opened this issue 4 years ago • 21 comments

You currently can't tell directly from a CSSSupportsRule whether the condition is actually fulfilled or not. To do that you have to use CSS.supports(cssSupportsRule.conditionText).

Therefore I suggest to add a getter to CSSSupportsRule (or rather to CSSConditionRule which is overwritten by the derived interfaces) that returns whether the condition is met or not, e.g supported or fulfilled.

Sebastian

SebastianZ avatar Aug 23 '19 22:08 SebastianZ

Sounds reasonable to me

FremyCompany avatar Aug 26 '19 13:08 FremyCompany

I think that's a very straight-forward addition. So, setting Agenda+ to discuss it in a call.

Sebastian

SebastianZ avatar Jun 02 '22 21:06 SebastianZ

Maybe .isTrue or something else more generic? I think it would make sense to add this to CSSConditionRule generically, not just to CSSSupportsRule.

fantasai avatar Jun 07 '22 21:06 fantasai

MediaQueryList has .matches, maybe that's good enough?

emilio avatar Jun 07 '22 22:06 emilio

(as a name, I mean)

emilio avatar Jun 07 '22 23:06 emilio

But on CSSConditionRule it's a bit tricky, because container rules need the element as an input too, to know whether the condition matches.

emilio avatar Jun 07 '22 23:06 emilio

With the changes for CSSContainerRule discussed in #7033, this can stay a simple getter because the query container is determined by the container name and query.

Sebastian

SebastianZ avatar Jun 08 '22 07:06 SebastianZ

matches rather refers to matching elements, though in case of CSSSupportsRule this is not the case. isTrue sounds a little too generic to me regarding the derived rules. Maybe isConditionMet or something? Anyway, I don't have a strong opinion on the name.

Sebastian

SebastianZ avatar Jun 08 '22 07:06 SebastianZ

Maybe met?

svgeesus avatar Jul 27 '22 16:07 svgeesus

But regardess of naming yes, I think we should have such a getter

svgeesus avatar Jul 27 '22 16:07 svgeesus

The CSS Working Group just discussed CSSSupportsRule should expose bool, and agreed to the following:

  • RESOLVED: Add .matches to CSSMediaRule and CSSSupportsRule
The full IRC log of that discussion <TabAtkins> Topic: CSSSupportsRule should expose bool
<faceless> present- (got to dash)
<TabAtkins> github: https://github.com/w3c/csswg-drafts/issues/4240
<astearns> ack chris
<TabAtkins> chris: Perfectly reasonable to have a getter to know whether the condition matches
<TabAtkins> chris: Most discussion is bikeshedding the name, not whether it shoudl exist or not
<TabAtkins> chris: Interested if there's arguments against
<fantasai> TabAtkins: Definitely should exist, could recreate by running it through existing APIs
<astearns> ack dbaron
<emilio> q+
<TabAtkins> dbaron: agree it shoudl exist. At some point when I drafted the IDL I made a common base class for supports and media. Might not exist now, but if we make a bool like this we should make it common between the rules
<astearns> ack fantasai
<TabAtkins> STrong agree
<TabAtkins> fantasai: Yeah, suggest putting it on CSSConditionRule superclass, which does exist
<TabAtkins> fantasai: emailio pointed out it's tricky on @container rules since they rely on the element being matched as well
<TabAtkins> fantasai: But we should have consistent naming even if it's individual methods on each subclass
<astearns> ack emilio
<TabAtkins> emilio: Yeah, superclass is tricky because CQs shouldn't have it
<TabAtkins> emilio: I think the API for CQs would look a bit different, would be a function that takes an element, and it would force layout, etc
<TabAtkins> emilio: So I think it should exist, but not on the superclass
<TabAtkins> TabAtkins: I suggest we just define a getter on the subclasses it makes sense for, yeah
<fantasai> ...
<fantasai> TabAtkins: .matches works, already on MQlist
<fantasai> TabAtkins: meaning carries over well
<TabAtkins> emilio: fwiw, "matches" is what we use internally in Gecko
<TabAtkins> chris: .met would work, but okay with .matches too
<TabAtkins> fantasai: Happy to go with .matches since MQList already has it
<chris> fine with matches
<fantasai> s/.../fantasai: Sure, but what's it called?/
<TabAtkins> astearns: So proposed resolution to add .matches to the relevant conditional rules
<TabAtkins> dholbert: Q about subclasses vs superclass
<TabAtkins> dholbert: Can we put in an intermediate superclass so it's shared?
<fantasai> TabAtkins: IDL supports this, but it is an observable change
<chris> emilio could you propose some IDL in the issue?
<fantasai> TabAtkins: we thought it would be useful for ConditionalRule, but less clear if it's worth it for this
<fantasai> astearns: Which rules are affected?
<emilio> chris: sure, `readonly attribute boolean matches;` on the two individual rules?
<fantasai> TabAtkins: @media and @supports
<TabAtkins> yeah, that's the IDL
<TabAtkins> RESOLVED: Add .matches to CSSMediaRule and CSSSupportsRule

css-meeting-bot avatar Jul 27 '22 16:07 css-meeting-bot

Late regrets that I couldn't make it to the call!

emailio pointed out it's tricky on @container rules since they rely on the element being matched as well

Unfortunately, my answer to that wasn't discussed on the call. And I think it would really be best if we added this to the CSSConditionRule superclass instead. So all classes deriving from it have it available. As mentioned in my previous comment, with the changes to CSSContainerRule discussed in #7033 the related element is determined by the other attributes of that interface. So .matches could be exposed as a simple getter there as well.

Sebastian

SebastianZ avatar Jul 27 '22 23:07 SebastianZ

@SebastianZ how do you get the query container? The container rule can be matched against different containers, I don't understand how that can work magically.

emilio avatar Jul 28 '22 09:07 emilio

As mentioned in my comment there. The CSSContainerRule would have two attributes reflecting the name and the query. Using those, matches can be a getter there as well.

So, matches will give you the information whether the container query matches a query container at the time of execution. It doesn't tell you whether it matches against a specific element or which query container it matches.

Sebastian

SebastianZ avatar Jul 29 '22 17:07 SebastianZ

Btw. matching a container query against a specific element is covered by #6205.

Sebastian

SebastianZ avatar Jul 29 '22 18:07 SebastianZ

As mentioned in my comment there. The CSSContainerRule would have two attributes reflecting the name and the query. Using those, matches can be a getter there as well.

Can you elaborate how that would work? Given a name + query pair you can't get an element, since container names are not guaranteed to be unique, which container you choose depends on which element are you styling.

emilio avatar Jul 29 '22 18:07 emilio

I totally disregarded that @container rules are special in that whether they match depends on the elements matched by the style rules' selectors within them.

So you're right, @emilio, a .matches getter isn't possible that way, sadly.

Sebastian

SebastianZ avatar Jul 31 '22 18:07 SebastianZ

While looking into this, I realized that CSSMediaRule.matches isn't quite easy either... A media rule might be disconnected from a document, accessed from another document, etc.

So at least we need to define what document we match against. The incumbent (caller) document? The document that the media rule is on, if any?

So that at least needs a spec clarification + test (easiest way to test this would be a same-origin iframe calling into CSSMediaRule.matches on a stylesheet originally from the parent document or vice-versa).

@tabatkins thoughts?

emilio avatar Aug 01 '22 21:08 emilio

I wonder whether that's enough of a non-edge-case to say that we should just abandon this idea and recommend window.matchMedia(mediaRule.mediaText) instead.

dbaron avatar Aug 02 '22 00:08 dbaron

I'd say .matches should always work in the context the related at-rule is in. I.e. if a media rule is disconnected from a document, conditions requiring a document to properly evaluate like (width > 1000px) would always return false. (Or it might even return undefined as that is what it is, but then it wouldn't have a clearly boolean return value.) Though preference-based conditions like (prefers-reduced-motion) would still evaluate normally.

If it's attached to a document, it is always evaluated against that document, even when accessed from another document. In other words, it should behave the same as its @media counterpart.

Though I wonder what the use cases are for checking whether a media rule matches when it or the stylesheet it is in is disconnected. CSSSupportsRule.matches has a much clearer use case in that case.

Sebastian

SebastianZ avatar Aug 02 '22 20:08 SebastianZ

Proposed edits, @SebastianZ and @emilio let me know if this works okay:

diff --git a/css-conditional-3/Overview.bs b/css-conditional-3/Overview.bs
index 35f48ca58..9324b8637 100644
--- a/css-conditional-3/Overview.bs
+++ b/css-conditional-3/Overview.bs
@@ -793,6 +793,7 @@ The {{CSSMediaRule}} interface represents a ''@media'' at-rule:
 [Exposed=Window]
 interface CSSMediaRule : CSSConditionRule {
     [SameObject, PutForwards=mediaText] readonly attribute MediaList media;
+    readonly attribute bool matches;
 };
 </pre>
 
@@ -808,6 +809,14 @@ js/CSSConditionRule.html
     for the list of media queries specified with the ''@media'' at-rule.
     <wpt title=".media returns a MediaList matching the @media condition."></wpt>
 
+  <dt><code>matches</code> of type {{bool}}, readonly
+  <dd>The <code>matches</code> attribute returns true
+    if the rule is in an stylesheet attached to a document
+    whose {{Window}} matches this rule’s {{CSSMediaRule/media}} [=media query=],
+    and returns false otherwise.
+
+    ISSUE: Stylesheet attached to a document isn't a well-defined concept right now.
+
   <dt><code>conditionText</code> of type <code>CSSOMString</code> (CSSMediaRule-specific definition for attribute on CSSConditionRule)
   <dd>The <code>conditionText</code> attribute (defined on the <code>CSSConditionRule</code> parent rule),
     on getting, must return the value of <code>media.mediaText</code> on the rule.
@@ -827,6 +836,7 @@ The {{CSSSupportsRule}} interface represents a ''@supports'' rule.
 <pre class='idl'>
 [Exposed=Window]
 interface CSSSupportsRule : CSSConditionRule {
+    readonly attribute bool matches;
 };
 </pre>
 
@@ -836,6 +846,10 @@ js/CSSConditionRule.html
 <wpt title="CSSSupportsRule represents an @supports rule."></wpt> -->
 
 <dl class='idl-attributes'>
+  <dt><code>matches</code> of type {{bool}}, readonly
+  <dd>The <code>matches</code> attribute returns the evaluation of
+      the [=CSS feature query=] represented in {{CSSConditionRule/conditionText}}.
+
   <dt><code>conditionText</code> of type <code>CSSOMString</code> (CSSSupportsRule-specific definition for attribute on CSSConditionRule)
   <dd>The <code>conditionText</code> attribute (defined on the <code>CSSConditionRule</code> parent rule),
     on getting, must return the condition that was specified,

fantasai avatar Aug 24 '22 21:08 fantasai

@fantasai looks good to me.

emilio avatar Feb 28 '24 18:02 emilio

Totally missed your comment, @fantasai. Sorry! It also looks good to me.

Sebastian

SebastianZ avatar Feb 29 '24 22:02 SebastianZ