Skip to main content
RapidDev - Software Development Agency
lovable-issues

Ensuring TailwindCSS Classes Apply Properly in Lovable

Tailwind CSS classes fail to apply in Lovable when they are dynamically constructed (Tailwind cannot detect them during build), when conflicting classes cancel each other out, or when the content array in tailwind.config.ts does not include all template files. Use the cn() utility from shadcn/ui for conditional classes, avoid string concatenation for class names, and add dynamic classes to the safelist.

Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate8 min read~10 minAll Lovable projects (Tailwind CSS v3+)March 2026RapidDev Engineering Team
TL;DR

Tailwind CSS classes fail to apply in Lovable when they are dynamically constructed (Tailwind cannot detect them during build), when conflicting classes cancel each other out, or when the content array in tailwind.config.ts does not include all template files. Use the cn() utility from shadcn/ui for conditional classes, avoid string concatenation for class names, and add dynamic classes to the safelist.

Why Tailwind CSS classes do not apply in Lovable projects

Tailwind CSS works by scanning your source files for class names and generating only the CSS for classes it finds. This is called 'purging' — it removes unused CSS to keep the bundle small. The problem is that Tailwind scans files as plain text at build time. If a class name is constructed dynamically at runtime (like `bg-${color}-500`), Tailwind never sees the full class name and does not generate the CSS for it. Another common issue in Lovable projects is class conflicts. When you apply both p-4 and p-8 to the same element, only one can win. Tailwind resolves conflicts by source order in the stylesheet, not by the order in your className string. The cn() utility function (included in all Lovable projects via shadcn/ui) solves this by using tailwind-merge to intelligently resolve conflicts. The content array in tailwind.config.ts tells Tailwind which files to scan. If a component file is outside the scanned paths (for example, in a folder not covered by the glob pattern), its classes will not be generated in the final CSS.

  • Dynamic class names — Tailwind cannot detect classes constructed with string interpolation at build time
  • Class conflicts — multiple utility classes compete for the same CSS property, and the wrong one wins
  • Content array incomplete — tailwind.config.ts does not scan all files that contain Tailwind classes
  • Important flag missing — other CSS (from shadcn/ui or custom styles) has higher specificity than Tailwind utilities
  • Dark mode class not toggling — dark: variants do not apply because the dark class is not on the html element

Error messages you might see

Tailwind class 'bg-blue-500' has no effect (element still has default background)

The class exists in your code but may be overridden by a more specific CSS rule, or the class is dynamically generated and was purged from the build. Check for conflicting classes and use the cn() utility.

Dynamic class 'bg-${color}-500' does not apply any styles

Tailwind cannot detect class names that are constructed with string interpolation. Use a mapping object instead: const colorMap = { red: 'bg-red-500', blue: 'bg-blue-500' }.

Custom Tailwind class not working after deployment but works in preview

The class is purged in the production build because Tailwind cannot find it in the scanned files. Add it to the safelist in tailwind.config.ts.

Before you start

  • A Lovable project where Tailwind CSS classes are not applying as expected
  • Browser DevTools to inspect which CSS rules are applied to an element
  • Access to Dev Mode to edit tailwind.config.ts

How to fix it

1

Use the cn() utility for conditional and conflicting classes

cn() uses tailwind-merge to resolve class conflicts intelligently, ensuring the last specified class wins

Every Lovable project includes the cn() utility at src/lib/utils.ts (provided by shadcn/ui). Use it instead of manually concatenating class strings. cn() merges classes, removes duplicates, and resolves conflicts. When you write cn('p-4', 'p-8'), it correctly outputs 'p-8' instead of both classes fighting.

Before
typescript
// BAD: class conflict — both p-4 and p-8 are applied
<div className={`p-4 ${isLarge ? 'p-8' : ''} bg-white`}>
Content
</div>
After
typescript
import { cn } from "@/lib/utils";
// GOOD: cn() resolves the conflict — p-8 wins when isLarge is true
<div className={cn("p-4 bg-white", isLarge && "p-8")}>
Content
</div>

Expected result: The element has p-8 when isLarge is true and p-4 when false. No conflicting classes are applied simultaneously.

2

Replace dynamic class names with a mapping object

Tailwind scans source files as text at build time — it cannot detect class names built with string interpolation

Instead of constructing class names dynamically (bg-${color}-500), create a mapping object where every possible class is written as a complete string. Tailwind can then detect all the classes during its scan and include them in the build output.

Before
typescript
// BAD: Tailwind never sees 'bg-red-500' or 'bg-blue-500'
function Badge({ color }: { color: string }) {
return <span className={`bg-${color}-500 text-white px-2 py-1 rounded`} />;
}
After
typescript
// GOOD: all class names are complete strings Tailwind can detect
const colorClasses: Record<string, string> = {
red: "bg-red-500",
blue: "bg-blue-500",
green: "bg-green-500",
yellow: "bg-yellow-500",
};
function Badge({ color }: { color: string }) {
return (
<span className={cn(
"text-white px-2 py-1 rounded",
colorClasses[color] || "bg-gray-500"
)} />
);
}

Expected result: All color variants are included in the build. The correct background color applies based on the color prop.

3

Add commonly used dynamic classes to the safelist

The safelist forces Tailwind to include specific classes in the build even if they are not found in scanned files

Open tailwind.config.ts and add a safelist array with classes that must always be available. This is a last resort for cases where you cannot avoid dynamic class names (like classes from a CMS or database). Use patterns for groups of related classes.

Before
typescript
export default {
content: ["./index.html", "./src/**/*.{ts,tsx}"],
theme: { extend: {} },
};
After
typescript
export default {
content: ["./index.html", "./src/**/*.{ts,tsx}"],
safelist: [
// Always include these classes even if not in source files
"bg-red-500", "bg-blue-500", "bg-green-500", "bg-yellow-500",
// Pattern: include all bg-{color}-500 classes
{ pattern: /bg-(red|blue|green|yellow|purple)-(100|500|900)/ },
],
theme: { extend: {} },
};

Expected result: Safelisted classes are always included in the CSS bundle, even if Tailwind cannot find them in scanned files.

4

Inspect and resolve CSS specificity conflicts

Tailwind utilities have low specificity — other CSS rules from shadcn/ui or custom styles can override them

Right-click the element in the browser preview and select Inspect. In the Styles panel, look at the applied CSS rules. If your Tailwind class appears but is crossed out, another rule with higher specificity is overriding it. Solutions: use the Tailwind important modifier (!) like !bg-blue-500, apply the style at a more specific selector level, or remove the conflicting CSS rule. If resolving Tailwind specificity conflicts across many shadcn/ui components requires systematic changes, RapidDev's engineers have fixed these patterns across 600+ Lovable projects.

Before
typescript
// Tailwind class is overridden by shadcn/ui button styles
<Button className="bg-blue-500">Click me</Button>
After
typescript
import { cn } from "@/lib/utils";
// Use cn() and the important modifier to override component styles
<Button className={cn("!bg-blue-500 hover:!bg-blue-600")}>Click me</Button>

Expected result: Your Tailwind class takes priority over the shadcn/ui component's default styles.

Complete code example

src/lib/utils.ts
1import { type ClassValue, clsx } from "clsx";
2import { twMerge } from "tailwind-merge";
3
4/**
5 * Combines class names with intelligent conflict resolution.
6 * Uses clsx for conditional logic and tailwind-merge to
7 * resolve Tailwind class conflicts (e.g., p-4 + p-8 = p-8).
8 *
9 * Usage:
10 * cn("base-classes", isActive && "active-classes", className)
11 * cn("p-4 bg-white", isLarge && "p-8") // resolves to "p-8 bg-white"
12 */
13export function cn(...inputs: ClassValue[]) {
14 return twMerge(clsx(inputs));
15}
16
17/**
18 * Type-safe mapping for dynamic Tailwind classes.
19 * Use this instead of string interpolation like `bg-${color}-500`.
20 */
21export const statusColors: Record<string, string> = {
22 active: "bg-green-100 text-green-800",
23 inactive: "bg-gray-100 text-gray-800",
24 pending: "bg-yellow-100 text-yellow-800",
25 error: "bg-red-100 text-red-800",
26} as const;
27
28export const sizeClasses: Record<string, string> = {
29 sm: "text-sm px-2 py-1",
30 md: "text-base px-4 py-2",
31 lg: "text-lg px-6 py-3",
32} as const;

Best practices to prevent this

  • Always use the cn() utility from @/lib/utils for conditional classes — it resolves Tailwind conflicts correctly
  • Never construct class names with string interpolation (bg-${color}-500) — use a mapping object with complete class strings
  • Keep the content array in tailwind.config.ts up to date — ensure it covers all files that contain Tailwind classes
  • Use the safelist only as a last resort for truly dynamic classes that cannot be expressed as complete strings in code
  • Inspect elements with DevTools when a class does not apply — check the Styles panel for overriding rules
  • Use the Tailwind important modifier (!) sparingly to override shadcn/ui component styles
  • Test Tailwind classes after building for production — some classes that work in dev may be purged in the production build

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I have a Lovable.dev project using Tailwind CSS and some classes are not applying correctly. Here is the problem: - Element: [describe the element] - Classes applied: [paste the className] - Expected style: [what it should look like] - Actual style: [what it actually looks like] Here is my tailwind.config.ts: [paste it] Please help me: 1. Identify why the classes are not applying 2. Fix any class conflicts using the cn() utility 3. Replace any dynamic class names with a mapping object 4. Update the safelist if needed

Lovable Prompt

Some Tailwind classes in @src/components/[filename] are not applying correctly. Check for class conflicts and replace any string-interpolated class names (like `bg-${color}-500`) with a mapping object. Use the cn() utility from @src/lib/utils for all conditional class logic. Do not change any other components.

Frequently asked questions

Why is my Tailwind class not working in Lovable?

The three most common causes are: the class is dynamically constructed and was purged during build, another CSS rule has higher specificity and overrides it, or the content array in tailwind.config.ts does not scan the file containing the class. Inspect the element in DevTools to see which rules apply.

What is the cn() utility and should I use it?

cn() is a function included in all Lovable projects (via shadcn/ui) that combines clsx and tailwind-merge. It resolves class conflicts intelligently — when you pass conflicting classes like 'p-4' and 'p-8', it keeps only 'p-8'. Always use it for conditional or merged class names.

Why does my Tailwind class work in preview but not after deployment?

Tailwind's production build purges unused classes. If the class is dynamically constructed (bg-${color}-500), Tailwind cannot detect it during the scan and removes it. Use a mapping object with complete class strings, or add the class to the safelist in tailwind.config.ts.

How do I override shadcn/ui component styles with Tailwind?

Use the cn() utility and the Tailwind important modifier: className={cn('!bg-blue-500')}. The exclamation mark adds !important to the generated CSS, overriding the component's default styles.

What is the Tailwind safelist?

The safelist in tailwind.config.ts forces Tailwind to include specific classes in the CSS bundle even if they are not found in scanned files. Use it for classes that come from dynamic sources like a CMS or database. It is a last resort — prefer mapping objects for most dynamic class scenarios.

What if I can't fix this myself?

If your project has widespread Tailwind styling issues across many components, especially involving complex theme customization and shadcn/ui overrides, RapidDev's engineers have resolved these patterns across 600+ Lovable projects.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your issue.

Book a free consultation

Need help with your Lovable project?

Our experts have built 600+ apps and can solve your issue fast. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.