You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
What should pseudo(type) return for elements that can't have pseudo elements? #12159
Description: CSSPseudoElement object is returned from pseudo(type) if type is parsed correctly, but what about elements that can't have pseudo elements - e.g. <input> and ::before?
Possible solutions:
Return a CSSPseudoElement object (whose state/computed style then reflects non-generation)
Pros:
API Consistency: Element.pseudo(validPseudoTypeString) always returns a CSSPseudoElement object. null is reserved only for invalid/unrecognized type strings.
Separation of Concerns: Element.pseudo() provides the handle; .exists (potentially) on that handle reveals rendering state as per CSS rules.
Robust Introspection: Allows developers to get the object and check its computed style (e.g., display: "none", content: "none") to confirm and understand its non-rendered state.
Alignment with Highlight Pseudos: Consistent with ::selection where an object can exist even if no selection is active.
Forward Compatibility: If CSS rules change, the API behavior for Element.pseudo() remains stable.
Cons:
Indirect "Existence" Check: Developers need to get the object and then inspect its computed styles(or potentially .exists) to confirm it's not actually rendered, rather than just checking for null.
Potentially "Useless" Objects: Creates an object that might not correspond to anything visible or affecting layout.
Return null
Pros:
Direct Feedback: Immediately signals to the developer that this specific combination of element and pseudo element type is not valid or won't render.
Simpler "Existence" Check: null means it doesn't exist in this context; no further checks needed on a pseudo-object.
Cons:
Inconsistent API Signature: Element.pseudo() would return null for two different reasons (invalid pseudo selector string or valid selector on an incompatible element), making error handling more complex.
Less Introspection: Prevents developers from getting a handle to inspect why it doesn't render (e.g., to check default computed styles for such a conceptual pseudo).
Recommendation:
Return a CSSPseudoElement object. This approach is generally favored because it provides a more consistent and predictable API contract (null only for invalid pseudo element type strings), and the author can use e.g. exists to determine whether the object exists. The discussion is probably needed on if parent and element should be null in that case?
Inconsistent API Signature: Element.pseudo() would return null for two different reasons (invalid pseudo selector string or valid selector on an incompatible element), making error handling more complex.
I don't mind this "Con." If an author is looking to check for validity of a selector from script, I would point them to CSS.supports() instead.
The CSS Working Group just discussed What should `pseudo(type)` return for elements that can't have pseudo elements?, and agreed to the following:
RESOLVED: proposed: for a valid selector we will always return the CSSPseudoElement object
The full IRC log of that discussion
<ydaniv> sakhapov: this one is about entry point element.pseudo which always returns element if selector is valid
<flackr> q+
<ydaniv> ... for example input element can not generate pseudos, so question what to return in this case
<ydaniv> ... false or otherwise
<ydaniv> ... no preference here, looking for ideas
<astearns> ack flackr
<ydaniv> flackr: one clarification, if selector is invalid, does it throw?
<ydaniv> sakhapov: I think we return null
<ydaniv> flackr: I think in other APIs we throw, so should consider changing
<ydaniv> ... I think if the pseudo could conditionally exist then should be good to return an interface of whether it exists
<kbabbitt> q+
<ydaniv> ... might be other cases where existence could change
<ydaniv> sakhapov: if wanna add scroll event listeners to scroll-marker then enter a loop and just request scroll-marker on every element, and then exceptions would look ugly
<ydaniv> flackr: if the selector that you wrote is never valid we should throw
<ydaniv> sakhapov: question if we should throw on before/after
<ydaniv> flackr: in that case condition can't change
<TabAtkins> q+
<astearns> ack kbabbitt
<ydaniv> kbabbitt: just thinking on Rob's point, gets weird in some cases, for example with checkboxes, can change the state and get different pseudo, kind of weird
<ydaniv> sakhapov: in this scenario defined to always return
<astearns> ack TabAtkins
<ydaniv> ... we can discuss back in the issue
<ydaniv> TabAtkins: on Rob's point, the condition of existence, isn't necessarily a static thing, like password reveal icon
<ydaniv> ... definitely don't want a throw to happen
<ydaniv> ... I think "knowing" is definitly helpful
<ydaniv> flackr: was only advocating to cases to throw if not valid
<flackr> similar to element.animate: https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-pseudoelement
<ydaniv> TabAtkins: ok
<kbabbitt> I think querySelector throws on an invalid selector also
<ydaniv> sakhapov: for now returns null when not valid
<ydaniv> TabAtkins: if at all possible throwing on non-valid stuff is ideal
<ydaniv> ... there's a chance it's not web compat
<ydaniv> ... but should be silent if valid but not getting anything right now
<ydaniv> sakhapov: but then in cases you get null and change type of element then you once again call for same pseudo, but then you query again you get an element
<kbabbitt> q+
<ydaniv> ... is that stable?
<ydaniv> TabAtkins: if your input goes to password and back, if you queried on all states you get the first option first and last should be same
<TabAtkins> TabAtkins: if you change an input from password, to text, then back to password, and ask for a password-reveal pseudo-element all three states, you should get the same object back on the first and third calls, ideally (despite getting null on the second call)
<TabAtkins> TabAtkins: And that should be addressable with `[SameObject]` and some prose, I think
<ydaniv> kbabbitt: kind of related, for password control, grab a pseudo element for that, and then change input type to text where pseudo doesn't exist, and query, not clear what behavior should be
<flackr> q+
<ydaniv> TabAtkins: I'd assume that when they don't exist it would reveal the change
<TabAtkins> s/the change/the change via the "exists" boolean/
<ydaniv> kbabbitt: in that case, does the null return makes sense? how is it different than returning object and checking for existence?
<ydaniv> TabAtkins: if you know at time of call it doesn't exist returning something that may change is bad design
<astearns> ack kbabbitt
<ydaniv> ... I think in common case if you're not changing things around, it's more useful to get no result back if doesn't exist ATM
<ydaniv> kbabbitt: going to previous issue should be good to have use-cases
<astearns> ack flackr
<ydaniv> flackr: I feel I'm on the other side, there's a pref cost on checking for existence, having event listeners and style resolution
<ydaniv> ... we'd like developers to be able to set stuff up if they're not in the documnet
<ydaniv> astearns: Rob convinced me
<TabAtkins> +1 to resolve on always returning a pseudoelement, yeah
<ydaniv> proposed: for a valid selector we will always return the CSSPseudoSelector object
<sakhapov> CSSPseudoElement object
<ydaniv> proposed: for a valid selector we will always return the CSSPseudoElement object
<ydaniv> ... objections?
<ydaniv> RESOLVED: proposed: for a valid selector we will always return the CSSPseudoElement object
<TabAtkins> ScribeNick: TabAtkins
Activity
kbabbitt commentedon Jun 24, 2025
I don't mind this "Con." If an author is looking to check for validity of a selector from script, I would point them to
CSS.supports()instead.css-meeting-bot commentedon Jun 25, 2025
The CSS Working Group just discussed
What should `pseudo(type)` return for elements that can't have pseudo elements?, and agreed to the following:RESOLVED: proposed: for a valid selector we will always return the CSSPseudoElement objectThe full IRC log of that discussion
<ydaniv> sakhapov: this one is about entry point element.pseudo which always returns element if selector is valid<flackr> q+
<ydaniv> ... for example input element can not generate pseudos, so question what to return in this case
<ydaniv> ... false or otherwise
<ydaniv> ... no preference here, looking for ideas
<astearns> ack flackr
<ydaniv> flackr: one clarification, if selector is invalid, does it throw?
<ydaniv> sakhapov: I think we return null
<ydaniv> flackr: I think in other APIs we throw, so should consider changing
<ydaniv> ... I think if the pseudo could conditionally exist then should be good to return an interface of whether it exists
<kbabbitt> q+
<ydaniv> ... might be other cases where existence could change
<ydaniv> sakhapov: if wanna add scroll event listeners to scroll-marker then enter a loop and just request scroll-marker on every element, and then exceptions would look ugly
<ydaniv> flackr: if the selector that you wrote is never valid we should throw
<ydaniv> sakhapov: question if we should throw on before/after
<ydaniv> flackr: in that case condition can't change
<TabAtkins> q+
<astearns> ack kbabbitt
<ydaniv> kbabbitt: just thinking on Rob's point, gets weird in some cases, for example with checkboxes, can change the state and get different pseudo, kind of weird
<ydaniv> sakhapov: in this scenario defined to always return
<astearns> ack TabAtkins
<ydaniv> ... we can discuss back in the issue
<ydaniv> TabAtkins: on Rob's point, the condition of existence, isn't necessarily a static thing, like password reveal icon
<ydaniv> ... definitely don't want a throw to happen
<ydaniv> ... I think "knowing" is definitly helpful
<ydaniv> flackr: was only advocating to cases to throw if not valid
<flackr> similar to element.animate: https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-pseudoelement
<ydaniv> TabAtkins: ok
<kbabbitt> I think querySelector throws on an invalid selector also
<ydaniv> sakhapov: for now returns null when not valid
<ydaniv> TabAtkins: if at all possible throwing on non-valid stuff is ideal
<ydaniv> ... there's a chance it's not web compat
<ydaniv> ... but should be silent if valid but not getting anything right now
<ydaniv> sakhapov: but then in cases you get null and change type of element then you once again call for same pseudo, but then you query again you get an element
<kbabbitt> q+
<ydaniv> ... is that stable?
<ydaniv> TabAtkins: if your input goes to password and back, if you queried on all states you get the first option first and last should be same
<TabAtkins> TabAtkins: if you change an input from password, to text, then back to password, and ask for a password-reveal pseudo-element all three states, you should get the same object back on the first and third calls, ideally (despite getting null on the second call)
<TabAtkins> TabAtkins: And that should be addressable with `[SameObject]` and some prose, I think
<ydaniv> kbabbitt: kind of related, for password control, grab a pseudo element for that, and then change input type to text where pseudo doesn't exist, and query, not clear what behavior should be
<flackr> q+
<ydaniv> TabAtkins: I'd assume that when they don't exist it would reveal the change
<TabAtkins> s/the change/the change via the "exists" boolean/
<ydaniv> kbabbitt: in that case, does the null return makes sense? how is it different than returning object and checking for existence?
<ydaniv> TabAtkins: if you know at time of call it doesn't exist returning something that may change is bad design
<astearns> ack kbabbitt
<ydaniv> ... I think in common case if you're not changing things around, it's more useful to get no result back if doesn't exist ATM
<ydaniv> kbabbitt: going to previous issue should be good to have use-cases
<astearns> ack flackr
<ydaniv> flackr: I feel I'm on the other side, there's a pref cost on checking for existence, having event listeners and style resolution
<ydaniv> ... we'd like developers to be able to set stuff up if they're not in the documnet
<ydaniv> astearns: Rob convinced me
<TabAtkins> +1 to resolve on always returning a pseudoelement, yeah
<ydaniv> proposed: for a valid selector we will always return the CSSPseudoSelector object
<sakhapov> CSSPseudoElement object
<ydaniv> proposed: for a valid selector we will always return the CSSPseudoElement object
<ydaniv> ... objections?
<ydaniv> RESOLVED: proposed: for a valid selector we will always return the CSSPseudoElement object
<TabAtkins> ScribeNick: TabAtkins
[css-pseudo-4] Add a note explaining Element.pseudo() behaviour w3c#1…
[css-pseudo-4] Add a note explaining Element.pseudo() behaviour w3c#1…
[css-pseudo-4] Add a note explaining Element.pseudo() behaviour #12159 (