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

Add an option to prevent removal of unused CSS selectors/classes #5804

Closed
brgrz opened this issue Dec 16, 2020 · 19 comments
Closed

Add an option to prevent removal of unused CSS selectors/classes #5804

brgrz opened this issue Dec 16, 2020 · 19 comments

Comments

@brgrz
Copy link

brgrz commented Dec 16, 2020

Is your feature request related to a problem? Please describe.

In general, removal of unused CSS is a good thing. From time to time I'd like to opt out of it, for example I'm trying to style <svg> tags which are not yet present in the markup (lazy loaded with fetch). Svelte removes the styles for svg selector since no markup yet exists.

Describe the solution you'd like

Ideally something like :global for example :keep.

:keep(.icon svg) {
  width: 50%;
  height: 50%;
}

There's actually already a workaround and that is to use the :global selector from svelte-preprocess and if I use it with the styles that I don't want removed it works fine. Obviously, with a side effect of moving the targeted styles to root, which is unwanted.

I'd just like to have an option to prevent unused styles optimization occasionally.

Describe alternatives you've considered

The forementioned :global workaround.

How important is this feature to you?

not super crucial at the moment but would be nice to have

@stephane-vanraes
Copy link
Contributor

Note that :global doesn't need to be top level, you can nest it inside another selector .icon :global(svg) { ... } this style will now only apply to svgs that are descendents of .icon. Doing this keeps the benefit of scoping you would like to have.

@brgrz
Copy link
Author

brgrz commented Dec 16, 2020

Oh, missed that, sweet!

@Conduitry
Copy link
Member

As mentioned, you can make only part of the selectors global. See also the old issue #1594.

@brgrz
Copy link
Author

brgrz commented Dec 16, 2020

@Conduitry This appears to be a common issue people have. I searched but didn't find it in the Issues. Would it be possible to add this either to the tutorial or the API docs to make it more prominent?

@robin-shine
Copy link

@Conduitry This appears to be a common issue people have. I searched but didn't find it in the Issues. Would it be possible to add this either to the tutorial or the API docs to make it more prominent?

I strongly agree with “This appears to be a common issue people have.” is it possible to provide an option to prevent the removal of unused CSS selectors/classes

@srsholmes
Copy link

srsholmes commented Oct 23, 2021

I just cam across this issue as well, when adding classes conditionally / outside of the normal rendering logic. I think a comment above the selector would be sufficient to override the automatic removal of the css. maybe something like this

 /* css-keep-me */
  .result-item.highlight {
    background: orange;
  }

This is not that intuitive, although currently works (for anyone finding this later).

.result-item:global(.highlight) {
 background: orange;
}

@lanxeon
Copy link

lanxeon commented Nov 5, 2021

How would this work in a scss setting with nested classes? For example:

<style lang="scss">
  button {
    width: 80px;
    color: #00000099;
    opacity: 80%;

    &.orange {
      .dot {
        color: #ff9100;
      }

      &.active {
        background-color: #ff9100;
        color: #fff;
      }
    }

    &.blue {
      .dot {
        color: #69bcff;
      }

      &.active {
        background-color: #69bcff;
        color: #fff;
      }
    }

    &.purple {
      .dot {
        color: #5c6bc0;
      }

      &.active {
        background-color: #5c6bc0;
        color: #fff;
      }
    }

    &.green {
      .dot {
        color: #66bb6a;
      }

      &.active {
        background-color: #66bb6a;
        color: #fff;
      }
    }
  }
</style>

@EskelCz
Copy link

EskelCz commented Apr 11, 2022

Why is this closed? :( I would say the workaround isn't a proper solution, the issue remains.

@benzara-tahar
Copy link

this should not be closed, I am strugling to make resuable styles with tailwindcss using for example

.heading {
	@apply max-w-xl font-bold leading-tight tracking-tight text-gray-700 dark:text-white;
}

all dark: selectors are purged!

the ideal solution is to keep the warning about statically unused selectors (although they might be used dynamically in a way the svelte compiler doesn't know), but prevent purging these selectors. Or, at least provide an option to enable/disable removing unused css styles.

@baseballyama
Copy link
Member

I see. This is actual case.
Hum... Should the compiler just output warnings and not purge?
Personally We can think that the warnings are there but not remove means that CSS is needed for some reason.

But I'm not sure that just we should add compile option or just removing purge feature...

If not removed the CSS despite the warning, it can consider that CSS is necessary for some reason, so personally I think we can consider that purge is meaningless.

@pitAlex
Copy link

pitAlex commented May 10, 2022

I see. This is actual case. Hum... Should the compiler just output warnings and not purge? Personally We can think that the warnings are there but not remove means that CSS is needed for some reason.

But I'm not sure that just we should add compile option or just removing purge feature...

If not removed the CSS despite the warning, it can consider that CSS is necessary for some reason, so personally I think we can consider that purge is meaningless.

I just started using svelte and I am already blocked because of this. In my situation, the components I am targeting are coming from an external source (like a node module package). This really needs to be addressed.

@blake-regalia
Copy link

blake-regalia commented Jun 18, 2022

This problem plagues my projects whenever an inlined component adds classes dynamically, and the parent adds styling. Global scopes have unintended side effects as the selector starts matching elements in other, unrelated components.

I use the following workaround.

<style>
  .welcome { color: red; }
</style>

<!-- workaround is to show the preprocessor that some branch uses the welcome class, so don't remove it -->
{#if false}
    <span
        class:welcome={true}
    />
{/if}

<!-- svelte would otherwise remove the seemingly unused `.welcome` css class, altho we actually do use it here -->
<SomeComponent classNames='welcome'>
   ...
</SomeComponent>

@stop-amertime
Copy link

stop-amertime commented Jul 7, 2022

The promise of Svelte is simple reactivity, and the promise of the all-in-one style/markup/script in components is to allow locally scoped classes, with simple descriptive names like "column". But then, if you want reactive classes, you have to actually memorise the names of the global styles you've made, and then remember not to use those names again. It's a hack-job.

But worst of all - it's entirely unintuitive, and trips up new users. When I was first using Svelte, this led me to such a long process of debugging, in pure frustration at why CSS was completely ignoring me - was I being overriden? Was the selector invalid? No, it isn't even appearing in Devtools. Was my javascript incorrect? No, it looks fine...

Eventually, and after some googling, I realised that Svelte was simply deleting my CSS opaquely. Who would even consider that?

Of course there's an argument that if you import some gigantic external stylesheet and don't use most of it, Svelte is gaining much efficiency and that's a good thing.But if one writes some CSS, by hand, directly inside a component, and doesn't remove it despite a warning, why would anyone suspect it to be tree-shaken, on a line-by-line basis?

This is the kind of thing that makes a framework feel shoddy, and really leaves an impression. Either:

  • The warning should make it VERY CLEAR, at least, that the CSS will be deleted, and telling you how to make it not do that, similar to how Typescript offers an inline option to add a ts-ignore flag rather than making you go to the docs to figure it out.
  • BETTER: there should be an override in the <style> tag - like <style KEEP> that stops the CSS being deleted.
  • EVEN BETTER: automatically apply this to every style tag within a component. It's only really imported CSS files that are likely to be unused - how much css would I possibly even write INSIDE a single component?

@eddiegroves
Copy link

I was able to implement my use case using svelte-preprocess global attribute

Use case: Define styles with tailwindcss @apply in a component that will apply to elements inserted using {@html content}

@pawelgnatowski
Copy link

This problem plagues my projects whenever an inlined component adds classes dynamically, and the parent adds styling. Global scopes have unintended side effects as the selector starts matching elements in other, unrelated components.

I use the following workaround.

<style>
  .welcome { color: red; }
</style>

<!-- workaround is to show the preprocessor that some branch uses the welcome class, so don't remove it -->
{#if false}
    <span
        class:welcome={true}
    />
{/if}

<!-- svelte would otherwise remove the seemingly unused `.welcome` css class, altho we actually do use it here -->
<SomeComponent classNames='welcome'>
   ...
</SomeComponent>

I used this - thanks!

{#if false}
	<p class="dataError"></p>
{/if}

wanted to do just this:

{#if !dateFound}
	<p class="dataError" transition:fade>No data found for the date: {selectedValue} </p>
{/if}

<style>
	p.dataError {
		background-color: red;
	}
</style>

is there a better way?

@alvinometric
Copy link

This should be re-opened 🙏

@alvinometric
Copy link

cc: @dummdidumm

@pawelgnatowski
Copy link

Better yet - maybe some lazy loaded CSS?
Qwik style.
That would be a major win -agreed?

@Conduitry
Copy link
Member

This should not be re-opened.

@sveltejs sveltejs locked and limited conversation to collaborators Sep 22, 2022
@Conduitry Conduitry closed this as not planned Won't fix, can't repro, duplicate, stale Sep 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests