Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Regression: Svelte:global() parsing doesn't play nicely with SASS parent selectors: &[attr='value'] #8049

Closed
Labels
cssStuff related to Svelte's built-in CSS handling
@TylerRick

Description

@TylerRick

Describe the bug

Background

When usingsvelte withsvelte-preprocess andsass, it should be possible to use SASSparent selector& in the way we're used to, with the same semantics of being able to "take the parent selector and add something more specific to it" (my paraphrase).

Extending the semantics of SASS& to the Svelte world of:global()ness... It would seem to me thatif a& occurs within a block that isalready:global(), that the globalness of the resulting CSS selector should be preserved. Shouldn't it?

(Which has me wondering if this should actually be the responsibility ofsvelte-preprocess, which is supposed to be what takes SCSS input, and while preserving its meaning/intent, translates it to "bare Svelte" syntax that Svelte can understand.)

For example, let's say we have a list, where each element has a unique class or attribute...

<ul>  <lidata-i="0">...</li>  <lidata-i="1">...</li></li>

We may want to use some SCSS like this to group them together and style each of those unique elements...

li {/* Styles common to all li elements. And then styles for unique elements...*/&[data-i='0'] {background-color:red;  }&[data-i='1'] {background-color:blue;  }}

This produces the following CSS:

li {/* Styles common to all li elements. */}li[data-i="0"] {background-color: red;}li[data-i="1"] {background-color: blue;}

The Problem

Until I upgraded svelte recently, this was working as expected in my Svelte components, too:

<ul>  <Itemdata-i="0">...</Item>  <Itemdata-i="1">...</Item></li><stylelang="scss">:global(li) {&[data-i='1'] {background-color:blue;  }}</style>

InSvelte 3.37.0, this produced a<style> tag with this CSS:

li[data-i="1"]{background-color:blue}

It wasn't necessary to wrap the parent selector (&[data-i='1']) with:global(). In fact, doing so actually broke things because it caused the& to come through as-is, which is invalid CSS:

li&[data-i="1"]{background-color:blue}

Fast-forward toSvelte 3.38.0 or later, and we get somewhat opposite behavior and a breaking change... Try to keep doing this:

:global(li) {&[data-i='1'] {background-color:blue;  }}

and you get scolded:

Unused CSS selector ":global(li)[data-i="1"]"

and the selectorremoved.

Try to change it to this:

:global(li) {:global(&[data-i='1']) {background-color: blue;  }}

and you get the sameinvalid CSS as previous versions:

li&[data-i="1"]{background-color:blue}

Either way, it doesn't work! (Meaning, it broke my component when I upgraded.)

Workarounds

Of course I searched for a workaround...

Workaround 1: Don't use SASS — or at least not& — when dealing with a:global() style.

Obviously this works...

:global(li[data-i='1']) {background-color:blue;  }}

but I'd prefer to use&.

Workaround 2: Use:global {} feature from svelte-preprocess

... which lets you mark entire blocks as global (which is pretty useful, and preferable to workaround 1):

:global {li {&[data-i='1'] {background-color:blue;    }  }}

Root cause

The onlydocumented change to:global() behavior between 3.37.0 and 3.38.0 was#6222, so of course I assume that changeset (#6223) is what inadvertently broke this for SASS users.

What I would like to do isp:global(.xxx), while still scoped top within the component, it will treat.xxx as global (ie, do not go and match any selector written within:global())

I don'tquite understand#6222 enough to say why it should have broken it for this use case, but I would guess that in order to make it still add a.svelte-xyz scoping class for cases like this:

div:global(.bar) {color: red;}

and result in this (from thisdiff):

div.svelte-xyz.svelte-xyz.bar{color:red}

, it was necessary to change the logic to add the.svelte-xyz part if anypart of a selector did not have a:global(). And in my examples, the[attr] that svelte-preprocesscurrently gives us is outside of a:global().

Indeed, it looks like the root cause of this breaking change might go back as far as 3.18.1 and#4314 (comment):

As mentioned above, you need to use:global() around any portion of the selector that doesn't refer to this component, whether it's above us or below us in the tree.

Proposed solutions

I'm not entirely sure yet whether a solution for this would belong in...

  • svelte-preprocess (in order to preserve the intended globalness of the original SASS input when converting to CSS output that Svelte will understand)
  • or here insvelte (to be more tolerant of certain CSS input)

I noticed that among the use cases that#6223 was adding support for:

div:global(.bar) {color: red;}.foo:global(.bar) {color: red;}

, none of them involve a[attr] selector.

Is it possible that changing it so that it doesn't add the.svelte-xyz to selectors that containonly:global(...)[attr] would be enough to solve thing both for the#6223 use cases and the SASS use case presented here?

Then again, I might argue that even if you add aclass to a&, that the intended/desired outcome from a SASS user would be that anything within a:global(anything) { blockstays global:

:global(li) {&.item1 {background-color:red;  }&.item2 {background-color:blue;  }}

It's open to interpretation. But if we interpret the& as saying "exactly the same as the parent selector, but with...", then it should preserve the globalness and give us:global(li.item1).

Does that sound right?

And is it even possible to support that while also supporting the intent of#6222?

(I see a related report from a SASS userhere about a regression from 3.37.0 that also involves an[attr] selector,:global(div[row=one], but that's not quite the same problem since they actually get an error in that case:

global(...) can be at the start or end of a selector sequence, but not in the middle

)

Reproduction

https://github.com/TylerRick/svelte-sass_global_attr_regression

Logs

Unused CSS selector":global(li)[data-i="1"]"

Severity

blocking an upgrade

Metadata

Metadata

Assignees

No one assigned

    Labels

    cssStuff related to Svelte's built-in CSS handling

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp