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

Drop support for non-standard combinator arrangements #3340

Open
5 of 8 tasks
nex3 opened this issue Jun 18, 2022 · 10 comments
Open
5 of 8 tasks

Drop support for non-standard combinator arrangements #3340

nex3 opened this issue Jun 18, 2022 · 10 comments
Labels
blocked Waiting on another issue to be fixed enhancement New feature or request planned We would like to add this feature at some point

Comments

@nex3
Copy link
Contributor

nex3 commented Jun 18, 2022

Deprecation

Removal


Currently, Sass is very liberal when it comes to where explicit selector combinators can be written—much more so than CSS itself. We allow:

  • Multiple combinators between compound selectors (a > + b).
  • Combinators at the beginning of selectors (> a).
  • Combinators at the end of selectors (a >).

The latter two are useful when nesting style rules, but the former has no known use at all. Historically, we've said that we support these because they enable some browser hacks, but this seems to be purely hypothetical: browserhacks.com is the most comprehensive source of hacks I've found, and it doesn't list any hacks that are enabled by this support, even among its "legacy hacks".

In addition, supporting these selectors imposes substantial complexity on Sass implementations. They cause bugs (sass/dart-sass#1053) and make the data model more complex than it needs to be. This in turn makes bugs like #1807 that don't involve non-standard combinators more difficult to resolve.

Fortunately, these bogus combinators are unlikely to be widely-used in practice and have no effect in real-world browsers, which gives us considerable freedom to drop support for them without needing to do a lengthy deprecation period. We'll need to be careful to preserve the useful aspects of their behavior, and we'll probably want to make these produce errors eventually, but for the time being we can just cause them to omit selectors. In particular:

  • If any of a style rule's selectors contains a leading, trailing, or multiple combinator after nesting is resolved, omit that style rule from the generated CSS and emit a deprecation warning.

  • If a selector with a leading or trailing combinator is used with any extend-related infrastructure, emit a deprecation warning but proceed as usual for now. Although this isn't really desirable, it can produce valid CSS, as in selector.extend(".a .b", ".a", ".x >").

  • If a selector with a doubled combinator is used with any extend-related infrastructure, emit a deprecation warning and treat that selector as though it matches no elements (which is in fact the case).

Then, when we release the next major version of Dart Sass, we can start producing errors for the situations we had previously been producing deprecation warnings.

@nex3
Copy link
Contributor Author

nex3 commented Jun 18, 2022

I've opened a proposal for this: #3342

@nex3
Copy link
Contributor Author

nex3 commented Jun 22, 2022

The proposal has landed. Since this almost exclusively affects stylesheets that generate invalid CSS anyway, I don't think it's likely to be controversial so I'm going to give it two weeks for public comment before moving forward with the implementation.

@kerryj89
Copy link

kerryj89 commented Jul 5, 2022

Will this change make _header.scss invalid? I use this form and it makes for what I feel is a clean separation.

// layout/_index.scss
.layout-x {
    @include meta.load-css('header');
    ...
}
// layout/_header.scss
> header {
    background: blue;
}

@nex3
Copy link
Contributor Author

nex3 commented Jul 6, 2022

@kerryj89 That will specifically be invalid because meta.load-css() compiles the module's stylesheet to CSS before injecting it into the enclosing context, and > header isn't valid CSS. Since _header.scss isn't a valid CSS file anyway, I recommend putting it into an explicit mixin, which will continue to work.

nex3 added a commit to sass/sass-spec that referenced this issue Jul 15, 2022
nex3 added a commit to sass/dart-sass that referenced this issue Jul 15, 2022
nex3 added a commit to sass/dart-sass that referenced this issue Jul 15, 2022
nex3 added a commit to sass/dart-sass that referenced this issue Jul 15, 2022
nex3 added a commit to sass/dart-sass that referenced this issue Jul 15, 2022
nex3 added a commit to sass/dart-sass that referenced this issue Jul 18, 2022
@nex3 nex3 removed their assignment Jul 18, 2022
@nex3 nex3 added the blocked Waiting on another issue to be fixed label Jul 18, 2022
@jdelStrother
Copy link

From https://browserstrangeness.bitbucket.io/css_hacks.html#safari, I was hoping to use this to show a message to Safari 11 users -

html >> * #fallback-error { display: block; }

but this is now stripped out. Is there any workaround or do I need to find another approach?

@nex3
Copy link
Contributor Author

nex3 commented Aug 2, 2022

Since Safari 11.0 is used by substantially fewer users than the 2% cutoff we use for breaking browser changes, I think we'll have to consider it an acceptable loss here. Sorry for the trouble.

@kerryj89
Copy link

kerryj89 commented Apr 4, 2023

@kerryj89 That will specifically be invalid because meta.load-css() compiles the module's stylesheet to CSS before injecting it into the enclosing context, and > header isn't valid CSS. Since _header.scss isn't a valid CSS file anyway, I recommend putting it into an explicit mixin, which will continue to work.

Just to confirm I'm understanding you, does this seem okay for my situation?

// layout/_index.scss
@use 'header';

.layout-x {
    @include header.content;
    ...
}
// layout/_header.scss
@mixin content {
    > header {
        background: blue;
    }
}

@nex3
Copy link
Contributor Author

nex3 commented Apr 5, 2023

Yes, that will be valid. You can tell because it doesn't produce a deprecation warning in Sass today.

@GregJArnold
Copy link

GregJArnold commented Dec 11, 2023

I think I've hit an edge case on this.

.inputHeader {
  flex-direction: column;
  display: flex;
  
  @include tablet-and-desktop {
    flex-direction: row;
  
    > &:global(.space) {
      margin-top: 0;
    }
  }
} 

@mixin tablet-and-desktop {
  @media (min-width: #{$tablet-min}) {
    @content;
  }
}

This seems like it should fall under the nesting exception, because the @media selector goes as the outermost block.

@nex3
Copy link
Contributor Author

nex3 commented Dec 11, 2023

The issue with that code isn't the media query, it's the fact that the explicit parent selector in > &:global(.space) will cause the combinator > to appear at the beginning of the compiled selector.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked Waiting on another issue to be fixed enhancement New feature or request planned We would like to add this feature at some point
Projects
None yet
Development

No branches or pull requests

4 participants