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

:empty pseudo-selector (spec updated) #180

Closed
brandonmcconnell opened this issue Oct 2, 2022 · 12 comments
Closed

:empty pseudo-selector (spec updated) #180

brandonmcconnell opened this issue Oct 2, 2022 · 12 comments
Labels
focus-area-proposal Focus Area Proposal

Comments

@brandonmcconnell
Copy link

brandonmcconnell commented Oct 2, 2022

Description

:empty pseudo-selector (spec updated to also match elements with only whitespace)

Quoting the spec:

The :empty pseudo-class represents an element that has no children except, optionally, document white space characters. In terms of the document tree, only element nodes and content nodes (such as [DOM] text nodes, and entity references) whose data has a non-zero length must be considered as affecting emptiness; comments, processing instructions, and other nodes must not affect whether an element is considered empty or not.

Example: p:empty is a valid representation of the <p> elements in the following HTML fragment:

<p></p>
<p>
<p> </p>
<p></p>

Example: div:empty is not a valid representation of the <div> elements in the following fragment:

<div>text</div>
<div><p></p></div>
<div>&nbsp;</div>
<div><p>bla</p></div>
<div>this is not <p>:empty</p></div>

Rationale

The :empty pseudo-class is already widely supported among most modern browsers, but the spec has since changed to include matching for elements that contain only whitespace and no non-whitespace nodes or text nodes.

Quoting the amendment to this change from the spec:

Note: In Level 2 and Level 3 of Selectors, :empty did not match elements that contained only white space. This was changed so that that—given white space is largely collapsible in HTML and is therefore used for source code formatting, and especially because elements with omitted end tags are likely to absorb such white space into their DOM text contents—elements which authors perceive of as empty can be selected by this selector, as they expect.

In modern web development, we have bundlers that remove all non-whitespace characters from elements, so this is not normally an issue for a good number of us, but that limits the use of features like this to those of us running non-standard tools and further gate-keeps those without them, namely JAMstack devs who may have to ensure none of their elements are ever empty, so they can target in CSS them as expected.

It's the main reason for why we tend to see HTML like this in the wild, to ensure all elements contain no unexpected whitespace:

<div
    >Some content<span
        >some more content</span
    ></div
>

Related discussions:

Specification

https://w3c.github.io/csswg-drafts/selectors-4/#the-empty-pseudo

Tests

@brandonmcconnell brandonmcconnell added the focus-area-proposal Focus Area Proposal label Oct 2, 2022
@gsnedders gsnedders added this to the Interop 2023 milestone Oct 2, 2022
@foolip
Copy link
Member

foolip commented Oct 3, 2022

It looks like the spec change in question was w3c/csswg-drafts@2b42b64, but were any tests written for this?

If I'm reading the existing test right, which all browsers pass, the old behavior is still asserted:

https://github.com/web-platform-tests/wpt/blob/062bfa68f6358c63a273189f0f99c51b27f9d390/css/selectors/selectors-empty-001.xml#L40

If that's right, it makes this an unusual case, where we in fact already have interop, but the behavior isn't what people want.

@brandonmcconnell
Copy link
Author

@foolip That's correct. The current implementation (the old spec) is already interoperable, but I don't think any of the browsers support the new/revised spec. Mozilla might behind a flag, I think.

And you're correct, I believe, that there are no tests for the new spec, at least none I could fine thus far.

@foolip foolip moved this to Proposed in Interop 2023 Oct 7, 2022
@foolip foolip removed this from the Interop 2023 milestone Oct 7, 2022
@lilles
Copy link
Member

lilles commented Nov 1, 2022

We added a use-counter to try to measure the impact: https://chromestatus.com/metrics/feature/timeline/popularity/2624

Looks like this is too risky to change.

@brandonmcconnell
Copy link
Author

brandonmcconnell commented Nov 1, 2022

@lilles The intended use and official spec'd usage of :empty is to match for whitespace-only-containing elements, so I'd argue it's actually riskier to leave as is, where many devs use :empty expecting it to match elements with only whitespace and instead have to troubleshoot a while to discover that the implementation does not match the current spec.

At this point, a dev essentially has to either manually write their markup in some awful way or employ a tool to pre-uglify their code for them like Prettier (ironically) simply to prevent whitespace, so that :empty can be matched:

<div
    >Some content<span
        >some more content</span
    ></div
>

If this breaking change is considered too risky, I think the spec needs to be revisited and adjusted to reflect as much. At that point, a different pseudo selector would likely need to be introduced to match only non-whitespace (the current :empty spec), which I foresee becoming the new default of most devs, since most devs do not have a real use-case for the existing implementation of :empty.

It could be named something as simple as :whitespace-only (maybe something less verbose) that will match anywhere from 0 to Infinity whitespace characters, including spaces, tabs, and all other forms of simple whitespace.

@brandonmcconnell
Copy link
Author

It's also worth noting that for most/all of those sites listed under Sample URLs, making this change would have no impact whatsoever on their site, and :empty would still match when needed. If anything, those sites are going above the requirements and emptying out whitespace in order to be able to match, so :empty would actually be a welcome change.

@foolip
Copy link
Member

foolip commented Nov 1, 2022

@brandonmcconnell the risk is that a selector using :empty starts matching some element that it currently doesn't, applying rules where it's unexpected or breaking.

The use counter is triggered in cases where the selector currently doesn't match, but would with the changes. This happens on 2.5% of page loads. That doesn't by itself prove that anything would break, but it would require additional compat analysis to ship in Blink. Often what we do is to look at a random sample of sites that trigger the use counter and try to determine if the change would be breaking, as it seems like you've done with a few cases.

I agree the CSSWG should be made aware of the risk, @lilles can you file an issue?

@lilles
Copy link
Member

lilles commented Nov 1, 2022

@foolip See issue #1967

@brandonmcconnell
Copy link
Author

brandonmcconnell commented Nov 1, 2022

@foolip That's fair. I wasn't aware that the use counter was tracking for those specific instances that don't currently match but would now.

In that case, I agree in that CSSWG should likely adjust the spec and move this suggested functionality to a new pseudo-selector such as :whitespace-only.

Thank you both, @foolip and @lilles!

@foolip
Copy link
Member

foolip commented Nov 11, 2022

In the State of CSS 2022 question about browser incompatibilities, there was only a single mention of :empty, so not enough to make the top list in #248.

(I'm commenting on all proposals where I could find some mention at all in State of CSS results.)

@foolip
Copy link
Member

foolip commented Nov 11, 2022

In the MDN short survey on CSS & HTML, "CSS :blank and :empty pseudo-classes" was selected by ~19% of survey takers, putting it in the middle third of the 20 options. (There is some uncertainty as with any survey data.)

Since :blank and :empty were bundled we can't say which of them resonated more. (This was done to reduce the total number of options.)

@nairnandu
Copy link
Contributor

Thank you for proposing the :empty pseudo-selector for inclusion in Interop 2023.

We wanted to let you know that this proposal was not selected to be part of Interop this year. As mentioned in the comments, the spec change was deemed to be risky and warrants further discussion and resolution in the CSSWG.

For an overview of our process, see the proposal selection summary. Thank you again for contributing to Interop 2023!

Posted on behalf of the Interop team.

@brandonmcconnell
Copy link
Author

@foolip @nairnandu Could we look into resurrecting this one for Interop 2024 as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
focus-area-proposal Focus Area Proposal
Projects
No open projects
Status: Proposed
Development

No branches or pull requests

5 participants