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

Nested selectors with pseudo-elements result in invalid selectors #3119

Closed
yusuke-omae opened this issue May 16, 2023 · 5 comments
Closed

Nested selectors with pseudo-elements result in invalid selectors #3119

yusuke-omae opened this issue May 16, 2023 · 5 comments

Comments

@yusuke-omae
Copy link

esbuild version: 0.17.19

Suppose you enter the following CSS:

.foo {
  position:relative;
  &::before, &::after {
    position: absolute;
    content:"";
  }
}

expected transform css

.foo {
  position: relative;
}
.foo::before,
.foo::after {
  position: absolute;
  content: "";
}

actual transform css

.foo {
  position: relative;
}
.foo:is(::before, ::after) {
  position: absolute;
  content: "";
}

Because of the specification that pseudo-elements cannot be placed in the :is() selector, it is treated as an invalid selector in the current implementation.

Pseudo-elements cannot be represented by the matches-any pseudo-class; they are not valid within :is().

@evanw
Copy link
Owner

evanw commented May 16, 2023

As far as I can tell, pseudo-elements deliberately don't work with CSS nesting according to the CSS nesting specification (https://www.w3.org/TR/css-nesting-1/#ref-for-matches-pseudo%E2%91%A0):

The nesting selector cannot represent pseudo-elements (identical to the behavior of the :is() pseudo-class).

So I believe esbuild is working correctly here. Both .foo { &::before {} } and .foo:is(::before) {} are equivalent according to the specification, and are equally invalid. Transforming .foo { &::before {} } into .foo::before {} would be incorrect because it's not equivalent.

@yusuke-omae
Copy link
Author

@evanw Thanks for the quick and precise response.
I certainly recognized that my supposed selector should be invalid.
I realize that checking for invalid selectors at the point of entry is outside the scope of esbuild.

@evanw
Copy link
Owner

evanw commented May 16, 2023

I'll ask for clarification on this behavior. Right now there is only one implementation of this (Chrome) so it's hard to say what's a bug and what isn't. The CSS nesting specification is also still being actively changed so it's hard to say what the eventual behavior of CSS nesting is going to end up being. We'll have to wait and see. I know the people on CSS nesting want to remove this restriction. It sounds like they want to fix this by changing :is() to work with pseudo-elements, at which point this will automatically start working.

@evanw
Copy link
Owner

evanw commented May 16, 2023

I'm reopening this because it looks like you're right. That part of the specification only applies to pseudo-elements that come in through the & selector from the parent selector, but not to any of those that are joined with the & selector later.

@evanw evanw reopened this May 16, 2023
@evanw evanw closed this as completed in 905959f May 17, 2023
@yusuke-omae
Copy link
Author

@evanw thanks!

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

No branches or pull requests

2 participants