0

I want to associate TailwindCSS syntax interpretation with .vue (or Svelter / Astro) files so that the VSCode doesn't show errors for TailwindCSS directives in the <style> section, which would otherwise work.

<template>
...
</template>

<style scoped>
.my-element {
  @apply bg-red-500; /* Warning */
  /\
}
</style>

css(unknownAtRules): Unknown at rule @apply

I don't want to disable error reporting. It's quite frustrating that I have to disable a useful feature just because I want to use two different interpreters in one extension, in this case, vue and tailwindcss.

I can't add the support to files.associations because I primarily want to treat .vue files as Vue interpretation. The interpretation of TailwindCSS directives is secondary.

I'm not interested in other workaround solutions, such as lang='postcss', because that allows anything and doesn't provide hints for the individual directives.

I am using the TailwindCSS IntelliSense extension. Given its version, I don't expect 100% error-free functionality. I found a tailwindCSS.includeLanguages setting in its documentation. I understand correctly (?) that with this, I can identify different file extensions as HTML, CSS, or JavaScript, so I can give a secondary association to the TailwindCSS extension for specific files?

"tailwindCSS.includeLanguages": {
  "vue": "html",
},

For me, the warning still persists with this setting. If I am misunderstanding it, how can I make the TailwindCSS IntelliSense treat the Vue (or Svelte / Astro) file as HTML?

3
  • A bit of css.customData injection solves the syntax warning, but I only managed to get it working at the workplace level, which is counterproductive for 50 different projects. Commented Feb 14 at 15:41
  • Related: How to use @apply in Tailwind v4? Commented Aug 23 at 13:35
  • Related: Stop using @apply - Moni Commented Sep 17 at 12:53

3 Answers 3

1

By using the official TailwindCSS IntelliSense extension and setting the lang attribute to tailwindcss, the error messages disappear and hints appear while typing.

You don't even need to identify the Vue file as HTML for this to work.

<template>
...
</template>

<style lang="tailwindcss" scoped>
.my-element {
  @apply bg-red-500;
}
</style>

Note: I'm not convinced about when the modification was introduced.

Sign up to request clarification or add additional context in comments.

Comments

1

On the way to the correct answer, it's worth first clarifying the reason for the existence of @apply and what the main criticism against it is:

Confession: The apply feature in Tailwind basically only exists to trick people who are put off by long lists of classes into trying the framework.

You should almost never use it 😬

Reuse your utility-littered HTML instead.


Source: @adamwathan, #2, #3

<template>
...
</template>

<style scoped>
.my-element {
  background-color: var(--bg-red-500);
}
</style>

Basically, it's a fallback for when you can't do things the "proper" Tailwind way. But people tend to abuse it by simply writing CSS the way they always did (component classes in a separate CSS file). They can't get over the fact that Tailwind produces "messy" markup, so they retreat to their CSS file.

Source: Moni

That's the point of Tailwind - to style your elements on your elements, not in a CSS file.

@apply is a stopgap and shouldn't be used more than once or twice per project.


Source: Moni

So whenever possible, this should be avoided. For example, use Tailwind in the traditional way, with utilities in the HTML class attribute. Having many class names is not a problem. Especially with JS frameworks, it's easy to declare a component just once and then reuse it, so there's no code duplication.

Or even better, just use the classes in your markup like you're supposed to

<template>
  <div class="bg-blue-500">
    <h1 class="mb-2 text-3xl font-bold">Hello world!</h1>
    <p>Lorem ipsum dolor sit amet ...</p>
  </div>
</template>

Source: @adamwathan

But performance-related reasons can also be cited to argue against its use:

A ton of confusion amongst Tailwind users comes from not realizing that if you are using CSS modules, or <style> blocks in Vue/Svelte/Astro, your CSS pipeline separately for every single one of those blocks.

50 Vue components using <style> means Tailwind runs 50 separate times.


Source: @adamwathan

But if it is still needed, even here it's better to rely on global variables, which Tailwind CSS generates for every value declared in @theme:

For the best build performance, don't use Tailwind features in CSS modules or Vue/Svelte/Astro blocks, just rely on CSS variables.

<template>
  <div>
    <h1>Hello world!</h1>
    <p>Lorem ipsum dolor sit amet ...</p>
  </div>
</template>

<style>
  div {
    background-color: var(--color-blue-500);
  }
  h1 {
    font-size: var(--text-3xl);
    line-height: var(--text-3xl--line-height);
    font-weight: var(--font-weight-bold);
    margin-bottom: calc(2 * var(--spacing));
  }
</style>

Source: @adamwathan

But in the case of Tailwind CSS, to avoid duplication, it's better to do these in central CSS and then only use that in the local component. This results in much less duplication in the final CSS compared to creating separate CSS per component. Component-specific separated styles generate larger CSS, and although you load it in parts, in many cases you may load the same styling 2x, 3x, or multiple times, which is not very efficient.

The same thing happens by the way by just importing multiple CSS files in JS. Don't do that — import them all into one CSS file and load that one file in JS instead.


Source: @adamwathan

Conclusion

The use of @apply is not recommended for performance and increased production size reasons in separated <style> blocks or CSS modules. If you still need module CSS, reference CSS variables instead of class names to reduce the final size. But it's better to centralize all styling - even if this increases the size of the centralized CSS, it will still be smaller than having many fragmented duplicates.

If you avoid using @apply, the error mentioned in the question cannot occur.

I recommend using utilities more frequently in the HTML. The primary goal of Tailwind CSS is to minimize writing CSS code and creating custom CSS classes, so .header { ... } or other styling has little purpose with Tailwind CSS - it simply goes against the goal: using pre-made utility classes.

Essentially if you ever find yourself doing something like:

.btn {
  @apply px-4 py-2 rounded bg-blue-500 text-white;
}

Stop, slap yourself hard, once, and make a <Button> component instead:

<button class="px-4 py-2 rounded bg-blue-500 text-white">
  <slot/>
</button>

Source: Moni

2 Comments

The answer contains quite a few quotes, but I don't want to rephrase functionality and underlying content that others have already explained very well.
I didn't want to include just the links in the answer, since they point to social media sites or Discord, which might not be accessible to everyone. But I didn't want to copy them without proper attribution either.
0

The <style> tag needs additional information to understand what it's parsing (pure CSS by default). Add lang="postcss" to fix.

<style scoped lang="postcss">
.my-element {
  @apply bg-red-500;
}
</style>

As a side effect, this might remove syntax highlighting in VS Code, in which case, install the language-postcss extension (although deprecated, it still works)

1 Comment

Yes, I thought of those as well. I just feel that running the extension for this is a bit of an overkill. Writing lang=postcss is also somewhat inefficient. Although you always have to write TypeScript as well, so I don't really understand why I'm stuck on this...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.