how to use tailwinds @apply with @layer directive from a Svelte component
Asked Answered
M

3

13

I want to use apply to define some css setting on a component, and I also want to be able to overwrite it, like this:

<!-- CustomButton.svelte -->
<script>
    let className = '';
    export { className as class };
    export let label = 'Click me!';
</script>

<button class="custom-button {className}">{label}</button>

<style lang="postcss">
.custom-button {
    @apply bg-blue-400 font-bold text-white rounded-lg p-4;
}
</style>

And I want to use it like this:

<script>
    import CustomButton from './CustomButton.svelte';
</script>

<div class="w-screen h-screen flex justify-center items-center">
    <CustomButton class="bg-red-800" label="This is my button" />
</div>

That is, I want to be able to override my @applied settings

The problem is that the settings from thw @apply directives cannot be overriden by this line

<button class="custom-button {className}">{label}</button>

I understand that in order to do that I have to tell tailwind to generate the corresponding css in the components layer, that is, before the utilities.

If I enter the same css directive in my app.post.css file, before the @tailwind utilities line, or using the @layer components directives it works ok:

/* app.post.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

/* This works ok! */
@layer components {
  .custom-button {
    @apply bg-blue-400 font-bold text-white rounded-lg p-4;
  }
}

So, what I want is some way to tell tailwind to add the .custom-button setting I defined at my CustomButton.svelte component to the components layer, so that it could be overriden with inline clases.

If I try to do this in my CustomButton.svelte file

<style lang="postcss">
    @layer components {
        .custom-button {
            @apply bg-blue-400 font-bold text-white rounded-lg p-4;
        }
    }
</style>

I get the following error:

9:13:34 PM [vite] Internal server error: /home/sas/devel/apps/glas-it/apps/wingback/end-user-portal/src/routes/CustomButton.svelte?svelte&type=style&lang.css:1:1: `@layer components` is used but no matching `@tailwind components` directive is present.
  Plugin: vite:css

This issue is preventing me from using the @apply directive from any component.

Is there some way to achieve this?

Melvamelvena answered 5/9, 2021 at 0:15 Comment(0)
F
6

I was able to use @tailwind directives and functions on SvelteKit by importing it inside config :

// svelte.config.js

+import tailwindcss from 'tailwindcss';
+import autoprefixer from 'autoprefixer';

 const config = {
...
+  preprocess: sequence([
+    sveltePreprocess({
+      postcss: {
+        plugins: [tailwindcss, autoprefixer]
+      }
+    }),
+  ]),
...
}

NB: This was already set inside my postcss.config.cjs file but it did not work.

However, using the @tailwind components directive inside a <style> component tag :

  • Throws a warning with svelte-check ("Unknown at rule @tailwind")
  • Throws a warning with vite-plugin-svelte ("Unused CSS selector")

So, the easiest way seems to keep tailwind components inside your global app.css until better support.

Flemings answered 18/2, 2022 at 0:16 Comment(3)
where exactly is the preprocess, is it a key in the config object, or is it part of the plugins arrayEnticement
@Password-Classified it's a key in the config object, see github.com/sveltejs/svelte-preprocess#what-is-itFlemings
+1 & thanks. Just to say I had to tweak it for it to work.. ... preprocess: [ preprocess({ postcss: true, plugins: [tailwindcss, autoprefixer] }), ], ...Dextroglucose
H
1

Tailwind document miss some config in svelte.config.js. The config below work in new SvelteKit project.

import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // here you enable postcss, and you can use @apply directive
    preprocess: preprocess({ postcss: true }),

    ...
};

export default config;
Hodges answered 16/4, 2022 at 14:45 Comment(2)
Isn't everything in svelte-preprocess already enabled by default?Orthodox
No, you should enable postcss explicitly.Hodges
S
0

As per Tailwindcss documentation, you can't use @layer with @apply inside a framework's component, including Svelte (it actually mentions it). The solution is to create your own plugin to define applyable classes:

const plugin = require('tailwindcss/plugin')

module.exports = {
  // ...
  plugins: [
    plugin(function ({ addComponents, theme }) {
      addComponents({
        '.card': {
          backgroundColor: theme('colors.white');
          borderRadius: theme('borderRadius.lg');
          padding: theme('spacing.6');
          boxShadow: theme('boxShadow.xl');
        }
      })
    })
  ]
}
Shanitashank answered 20/1, 2022 at 14:13 Comment(1)
The docs mentions that you can't use @apply inside your component's style only for the custom class defined in your global CSS. OP's not trying to use @apply with a custom class.Flemings

© 2022 - 2024 — McMap. All rights reserved.