adding dynamic class name in svelte
Asked Answered
H

3

5

I am currently writing an app with svelte, sapper and tailwind. So to get tailwind working I have added this to my rollup config

svelte({
        compilerOptions: {
          dev,
          hydratable: true,
        },
        preprocess: sveltePreprocess({
          sourceMap: dev,
          postcss: {
            plugins: [
              require("tailwindcss"),
              require("autoprefixer"),
              require("postcss-nesting"),
            ],
          },
        }),
        emitCss: true,
      })

All in all this works, but I am getting some issues with dynamic class names.

Writing something like this always seems to work

  <div class={true ? 'class-a' : 'class-b'}>

both class-a and class-b will be included in the final emitted CSS and everything works as expected.

But when I try to add a variable class name it won't work. So imagine this:

  <div class={`col-span-6`}>

It will work exactly as expected and it will get the proper styling from the css class col-span-6 in tailwind.

But if I change it to this:

  <div class={`col-span-${6}`}>

Then the style won't be included. If I on the other hand already have a DOM element with the class col-span-6 then the styling will be added to both elements.

So my guess here is that the compiler sees that the css is not used and it gets removed. And I suppose that my question is then if there is any way to force in all the styling from tailwind? so that I can use more dynamic class names

and not sure if it is relevant but the component I have been testing this on, have this style block

<style>
  @tailwind base;
  @tailwind components;
  @tailwind utilities;
</style>

edit: can add that I am getting a bunch of prints in the log saying that there are unused css selectors that seems to match all tailwind classes

Hawkweed answered 2/1, 2021 at 17:50 Comment(0)
S
8

I think it was purgeCSS (built-in in tailwind 2.0) that did not recognize the dynamic classes.

It is difficult to solve this problem for every tailwind classes, but if you don't have a lot of these you can manually safe list those classnames:

// tailwind.config.js
module.exports = {
  purge: {
    content: ['./src/**/*.html'],

    // These options are passed through directly to PurgeCSS
    options: {
      // Generate col-span-1 -> 12
      safelist: [...Array.from({ length: 12. }).fill('').map((_, i) => `col-span-${i + 1}`],
    },
  },
  // ...
}
Swedish answered 2/1, 2021 at 18:39 Comment(0)
I
4

I think that when the class attribute is a variable or depends on a variable it will not used to extract style during compilation (class-${6} is not evaluated during compilation but during runtime), because svelte marks it as unused css selector because the value of that class attribute is not known when the code is compiled.

To force svelte to include your style you must mark it as global, and to do that we have two options:

<script>
// component logic goes here
</script>
div class={`class-${6}`}/>

option 1:

<style>
 :global(.class-6){
 // style goes here
 }
</style>

option 2: this will mark all your style as global

<style global>
 .class-6{
 // style goes here
 }
</style>
Irishirishism answered 3/1, 2021 at 17:16 Comment(0)
P
0

I encounter the same problem, <div class="pl-{indent*4}"> do not work in svelte.

My solution is to use inline style,

<div style="padding-left:{indent}rem">,

which is inferred from pl-1=padding-left: 0.25rem; /* 4px */.

I think it's convenient for simple class.

Popham answered 29/4, 2022 at 8:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.