#tailwind classes injected via $attrs not applying styles

10 messages · Page 1 of 1 (latest)

marsh remnant
#

tailwind classes are not being applied when injecting them via vue's $attrs. inspecting the nested div in chrome, bg-black is indeed passed to it, but no styles are applied...

// FooComponent.vue
<template>
  <div>
    <div v-bind="$attrs">
      <slot />
    </div>
  </div>
</template>

<script lang="ts" setup>
  defineOptions({ inheritAttrs: false });
</script>
  // ParentComponent.vue
  <FooComponent class="bg-black">Foo Component</FooComponent>
burnt muskBOT
#

Hi @marsh remnant. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The issue you're experiencing is due to how Vue handles attribute inheritance and class merging when using $attrs and inheritAttrs: false. When you pass a class (like bg-black) to a component, Vue normally merges it onto the root element of the component. However, when you use inheritAttrs: false and manually bind $attrs to a nested element, Vue does not automatically merge the class attribute; instead, it passes it as a plain attribute, which can break how Tailwind (and CSS in general) applies styles.

In your example:

// FooComponent.vue
<template>
  <div>
    <div v-bind="$attrs">
      <slot />
    </div>
  </div>
</template>

<script lang="ts" setup>
  defineOptions({ inheritAttrs: false });
</script>

When you use:

<FooComponent class="bg-black">Foo Component</FooComponent>

The class="bg-black" is passed via $attrs, but since it's not merged with the nested div's class, it doesn't get applied as a class—it's just an attribute, so Tailwind's styles don't take effect.

Solution:
You need to explicitly merge the class from $attrs with any existing classes on the nested div. For example:

<template>
  <div>
    <div :class="$attrs.class">
      <slot />
    </div>
  </div>
</template>

Or, if you want to bind all other attributes as well:

<template>
  <div>
    <div v-bind="Object.assign({}, $attrs, { class: $attrs.class })">
      <slot />
    </div>
  </div>
</template>

Alternatively, you can use the spread operator and merge classes properly.

#

This issue is also discussed in a similar context on Stack Overflow, where the solution is to ensure that the class attribute is correctly merged onto the intended element, not just passed via $attrs, especially when using inheritAttrs: false. If you want the class to apply to the root element, you should either not use inheritAttrs: false, or manually merge the class as shown above. See the detailed explanation and working example here: Encapsulating css class doesn't apply [nuxt3]

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@marsh remnant Kapa.ai is still learning and improving, please let me know how I did by reacting below.

marsh remnant
#

@burnt musk those suggestions dont work either

burnt muskBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

I'm sorry to hear the previous suggestions didn't work. Based on the knowledge sources provided, this issue is commonly related to how classes are passed and applied in Vue/Nuxt components, especially when using scoped styles or when the class is applied to a child element rather than the root.

A similar problem is discussed in this Stack Overflow post, where the solution was to ensure that the class (e.g., "primary") is applied to a wrapper div that actually contains the element you want to style. If you pass a class to a component and it doesn't get applied as expected, it's often because the class is not being merged onto the correct element in your component template.

Key point from the source:

The class being passed in the component usage definition, "primary", is being applied to the first "div" in the component definition but your CSS is written so that "primary" is applied to a wrapper "div" around "card-container".
Encapsulating css class doesn't apply [nuxt3]

What to check:

  • Make sure the class you pass from the parent is actually being merged onto the element you want to style.
  • If you use scoped styles, remember that they only apply to the component itself, not to parent-passed classes unless you explicitly handle them.

If you are still seeing the class attribute in the DOM but no styles are applied, it could also be due to how Tailwind CSS purges unused classes. If the class name is not statically present in your source files, Tailwind might not include it in the final CSS bundle. This is especially relevant if you use dynamic class names or pass them via $attrs.

#

From another source:

Tailwind engine bundles only the static icons declared in your code as explained here. So you need to hardcode them statically then get access them using a literal object or an array.
Nuxt v-bind not working with NuxtUI icons and util file

Summary:

  • Ensure the class is merged onto the correct element.
  • Avoid dynamic class names that Tailwind cannot detect at build time.
  • If using $attrs, manually merge the class attribute as needed.
  • If using scoped styles, remember their limitations.

If these steps do not resolve your issue, the knowledge sources do not provide a more specific solution for your exact scenario. If you can share more details or a minimal reproduction, it may help pinpoint the problem further.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@marsh remnant Kapa.ai is still learning and improving, please let me know how I did by reacting below.