Svelte: Hash for styles of my Svelte component is doubled

Created on 5 Feb 2020  路  11Comments  路  Source: sveltejs/svelte

When I put my component to REPL I have doubled styles hash and browser could not apply styles when I write them in separate css file.

component code:

<style>
.wpk-player {
  padding: 10px 15px;
}
.wpk-button svg {
  fill-opacity: 0.8;
}
</style>

<div class="wpk-player">
  <div class="wpk-player__buttons-1">
    <button class="wpk-button">
      <svg width="26" height="22" viewBox="0 0 26 22" xmlns="http://www.w3.org/2000/svg">
        <path d="M17.245 1.849c0-.92-.628-1.298-1.397-.837L.57 10.162c-.768.463-.768 1.217 0 1.678l15.278 9.148c.769.46 1.397.085 1.397-.836V1.849zm4.756 19.152H25s.956.074.994-1.001c.006-.197-.027-17.645.001-17.996.085-1.054-.996-1-.996-1h-3.001s-1.123-.059-1.001 1c.009.078.011 17.506.004 18-.016 1.161 1 .997 1 .997z" fill="#fff"/>
      </svg>
    </button>
  </div>
</div>

CSS output:
.wpk-player.svelte-4i1jb7.svelte-4i1jb7{padding:10px 15px}.wpk-button.svelte-4i1jb7 svg.svelte-4i1jb7{fill-opacity:0.8}

Also this component reproduce the same issue:

<div class="red">
  <div></div>
</div>

<style>
.red {color:red}
.red div {color: green}
</style>

CSS outut:

.red.svelte-wvyici.svelte-wvyici{color:red}.red.svelte-wvyici div.svelte-wvyici{color:green}

pending clarification

Most helpful comment

It also looks weird in dev tools and increases css bundle size by duplicating classes. This intended behavior is highly questionable.

All 11 comments

I noticed this as well, and I think this is only since one of the lastest updates.

Just checked, its like this since 3.16.6
https://svelte.dev/repl/183ee758c6364a1daf24e456945e4dff?version=3.16.5
https://svelte.dev/repl/183ee758c6364a1daf24e456945e4dff?version=3.16.6

4146

@tanhauhau would probably be the best person to confirm this, but this may be intended, to ensure specificity isn't messed up by the scoping class.

@tanhauhau would probably be the best person to confirm this, but this may be intended, to ensure specificity isn't messed up by the scoping class.

But if this is intended then it cause the problem: when I generate css as a separate file my styles do not apply at all to component html.

I noticed same issue.
It's not a bug in sense of produced code, but it's not smart enough. The fix is too general, it did increase specificity in too many cases when is not necessary and did not change code correctness = pass testes.

I hope, it will be fixed soon. Fixed CSS edge case (#4146) it's rare. But css it's bigger in all projects with ^3.16.6.

yes it is intended.

see this example:

<style>
  .a { color: red }
  .a .b .c .d .e .f .g { color: green }
  .a .b .c .d { color: green }
  .b .c .e { color: red }
</style>

to make sure each css selector declaration is scoped within the component, we add hash to the first and the last selector:

  .a.svelte-hash { color: red }
  .a.svelte-hash .b .c .d .e .f .g.svelte-hash { color: green }
  .a.svelte-hash .b .c .d.svelte-hash { color: green }
  .b.svelte-hash .c .e.svelte-hash { color: red }

to make sure that the class g, d or e is still within the component, not any element outside the component.

however if you noticed in the example, the specificity changed slightly, +1 and +2 in the class specificity.

this is okay in this example, but in the example https://github.com/sveltejs/svelte/issues/1277:

<div>
    <span>red</span>
    <span class='foo'>green</span>
</div>

<style>
  div span {
    color: red;
  }
  .foo {
    color: green;
  }
</style>

after adding the svelte-hash class, the specificity order changed:

  div.svelte-hash span.svelte-hash {
    color: red;
  }
  .foo.svelte-hash {
    color: green;
  }

to restore the specificity order, we have to make sure that each declarations have the equal number of svelte hash class added:

  div.svelte-hash span.svelte-hash {
    color: red;
  }
  .foo.svelte-hash.svelte-hash {
    color: green;
  }

which causes some selectors to have double svelte hash class.

@tanhauhau This is not smart, in many many cases with or without double/triple/... hash, specificity order is not changed. See first example (https://github.com/sveltejs/svelte/issues/4374#issue-560610725). With preprocessing you can check if it's needed or not. Right now css files are bigger in all projects.

Yea i agree with you, it's not quite smart.

My main problem with this is, that it is hard to overwrite specific things from a parent component.
I know, the svelte guys think a parent component should not overwrite styles, but coming from web-components, that just feels normal.

What i don't understand, when the component has one root element with a class, why does this root element needs a higher specificity?

<div class="Child">
  ...
</div>

So, in the parent I have to use

.Parent :global(.Child.Child.Child) {
  my: styles;
}
// or make everything !important
.Parent :global(.Child) {
  my: styles !important;
}

It also looks weird in dev tools and increases css bundle size by duplicating classes. This intended behavior is highly questionable.

EDIT: Replaced my comment with a new ticket https://github.com/sveltejs/svelte/issues/4795

Since in my case, the duplication of hashes doesn't apply consistently and introduces a bug.

thats a feature

I spent far too much time revalidating my Webpack config and testing plugins, only to eventually end up here.

  • Applying the same scoped class to an element multiple times to seemingly patch another scoping issue is a huge code smell.
  • If this is something that is going to stick around, it should be called out in the docs. Anywhere calling out how CSS is generated, in svelte-loader, and maybe in the example configs.
  • If this was added to address some other concern, how about an option to opt in or out of it?
  • This is the first time I've come across a specificity pattern like this. Seeing as how CSS specificity can be a tricky thing at times, I propose that the class is only added once, and any further specificity that needs to be added, should be done so by the Dev.

Currently I'm having to use !important on global styles (due to the multiple levels of specificity) which leads to it's own pitfalls. Please reconsider this functionality for the reasons I and the other comments have called out.

Just say no to .modal-body.svelte-11musit.svelte-11musit.svelte-11musit

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AntoninBeaufort picture AntoninBeaufort  路  3Comments

noypiscripter picture noypiscripter  路  3Comments

rob-balfre picture rob-balfre  路  3Comments

matt3224 picture matt3224  路  3Comments

mmjmanders picture mmjmanders  路  3Comments