Tailwind CSS - Add Custom Styles

In Tailwind CSS, adding custom styles means adding your own unique styles to the framework.

Often, the challenge with any framework is knowing what to do when it doesn't provide everything you need. Tailwind is built to be flexible and customizable, so you can adjust it to fit your project.

We will guide you through adjusting design settings, adding custom CSS, and using plugins to improve Tailwind's features.

Customizing Your Tailwind Theme

To customize things like font sizes, border styles, or spacing in Tailwind CSS, you'll need to make updates in the tailwind.config,js file. Here's how,

Add your custom settings to the tailwind.config.js file. For example, you can adjust font sizes and introduce new border styles this way.

Example

 
/** @type {import('tailwindcss').Config} */
module.exports = {
    theme: {
        fontSize: {
          'xs': '0.75rem',
          'sm': '0.875rem',
          'base': '1rem',
          'lg': '1.125rem',
          'xl': '1.25rem',
          '2xl': '1.5rem',
          '3xl': '1.875rem',
          '4xl': '2.25rem',
          '5xl': '3rem',
        },
        borderColor: {
          'primary': '#4a90e2',
          'secondary': '#d0021b',
          'tertiary': '#f5a623',
        },
        extend: {
          spacing: {
            'extra-wide': '40rem',
          },
          borderRadius: {
            'extra-large': '1.5rem',
          },
        },
    },
}

With the updated configuration, you can now use your custom font sizes and border styles in your HTML. Here's how to apply them.

Example

<div class="p-extra-wide border-primary border-2 
            rounded-extra-large text-3xl">
        This is a styled div with custom spacing, 
        border color, and font size.
</div>     

For more details on customizing your theme, check out the Theme Configuration documentation.

Arbitrary Values in Tailwind CSS

In Tailwind CSS, you generally use predefined design settings for styling you elements. However, when you need more precise control over your design, Tailwind allows you to use arbitrary values.

Sometimes, your design needs may not fit Tailwind's default options. For example, you might need a unique border width or padding that isn't available in the standard configuration. Arbitrary values allow you to set these custom sizes directly in your class names, giving you the precise look you want.

To apply arbitrary values in Tailwind CSS, use square bracket notation. This allows you to insert any valid CSS value directly into your class names.

Example

<!DOCTYPE html>
<html lang="en">
<head> 
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body class="p-4">
    <div class="border-[5px] p-[30px] bg-gray-300 rounded-lg shadow-lg">
        <h2 class="text-2xl font-bold mb-4 text-gray-800">Card Title</h2>
            This is an example card with custom border width and padding.
            The background color is a light gray, and additional 
            styling includes rounded corners and a shadow effect.
    </div>
</body>

</html>

In this example, border-[5px] sets the border width to 5 pixels, and p-[30px] adds 30 pixels of padding to all sides, showing the use of arbitrary values.

You can use arbitrary values such as spacing and positioning. Here's an example of how you can position an element with specific values and make it responsive.

Example

<div class="top-[117px] lg:top-[344px]">
      <!-- Your content here -->
</div>

Here, top-[117px] sets the position to 117 pixels from the top, and lg:top-[344px] moves it to 344 pixels from the top on large screens.

Arbitrary values can also be used for background colors, font sizes, and pseudo-elements.

Example

<div class="bg-[#bada55] text-[22px] before:content-['Festivus']">
    <!-- Your content here -->
</div>

Here, bg-[#bada55] changes the background color, text-[22px] sets the font size, and before:content-['Festivus'] adds "Festivus" before the content.

You can reference design tokens from your Tailwind configuration file for consistent styling.

Example

<div class="grid grid-cols-[fit-content(theme(spacing.32))]">
    <!-- Your content here -->
</div> 

Here, theme (spacing.32) gets the spacing values from your tailwind.config.js.

If you have defined CSS variables for your project, you can use them directly like this:

Example

<div class="bg-[--my-color]">
    <!-- Your content here -->
</div>

In this case, --my-color is a CSS variable defined elsewhere in your stylesheet.

Arbitrary properties

Arbitrary properties in Tailwind CSS allow you to use custom CSS values directly in utility classes with square brackets.

Sometimes, you might need a CSS property not included in Tailwind's utilities. For example, if you need a specific backdrop-filter effect not available by default, you can use arbitrary values.

Example

<div class="blurred-bg [backdrop-filter:blur(10px)]">
    <!-- Content with a blurred backdrop effect -->
</div>

You can also use Tailwind CSS arbitrary values for dynamic styles with modifiers. For example, adjust an element's backdrop-filter on hover.

Example

<div class="blurred-bg [backdrop-filter:blur(10px)] hover:[backdrop-filter:blur(20px)]">
    <!-- Content with a blurred backdrop effect -->
</div>

Tailwind CSS's arbitrary values are useful for adjusting CSS variables based on conditions like screen size. For example, set padding with a CSS variable that changes at different screen sizes:

Example

<div class="dynamic-padding [--padding-size:20px] 
            md:[--padding-size:40px] lg:[--padding-size:60px]">
    <!-- Content with padding based on screen size -->
</div>

Arbitrary Variants in Tailwind CSS

Arbitrary variants in Tailwind CSS enable you to apply custom styles directly in your HTML. Unlike predefined variants like hover: or md:, you can create new variants on the spot using square brackets.

Example

<!DOCTYPE html>
<html lang="en">
<head> 
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body class="p-4">
    <button class="bg-blue-500 text-white p-4 rounded 
                   hover:[background-color:#46b789]">
              Hover Over Me
    </button>
</body>

</html>

Check out the arbitrary variants documentation for more details.

Handling whitespace

Handling whitespace in Tailwind CSS means using underscore(_) instead of spaces in arbitrary values, which Tailwind then converts to spaces during build time.

Example

<!DOCTYPE html>
<html lang="en">
<head> 
    <script src="https://cdn.tailwindcss.com"></script> 
</head>

<body class="p-6"> 
    <div class="text-[line-height:2rem]">
        This text has a line height of 2rem.
    </div>
</body>

</html>

When you need to include spaces in URLs or paths where they're not allowed, use underscores(_). Tailwind CSS will keep the underscore and won't convert it to a space, for example.

Example

<div class="bg-[url('/hello_to_world.png')]....">
    <!-- Example of using underscores in URLs -->
</div>

When you need an underscore but a space is also valid, escape the underscore with a backslash('\'), and Tailwind will keep it as an underscore

Example

<div class="text-[letter-spacing:\0.1em]">
    <!-- -->
</div>

In JSX, where backslashes are often treated as escape characters, use String.raw() to ensure the backlash is correctly included on the output HTML.

Example

<div className={String.raw`before:content-['Welcome\_to our Website']`}>
    <!-- ... -->
</div>

Resolving ambiguities

In Tailwind, some utility classes have similar names but apply to different CSS properties. For example, border-4 sets the border width, while border-red-800 changes the border color to red. Even though both start with border, they handle different parts of the border styling.

When you use custom values, Tailwind automatically understands which property to apply based on the value you provide.

Example

<!DOCTYPE html>
<html lang="en">
<head> 
    <script src="https://cdn.tailwindcss.com"></script> 
</head>  

<body class="p-6"> 
      <div class="text-[22px]">
          This text has a font size of 22px.
      </div> 
      <div class="text-[#67aa55]">
          This text has a color defined by a hex code.
      </div>
</body>

</html>

Ambiguity can occur with CSS variables. For example, if you use text-[var(--my-var)], Tailwind can't tell if --my-var is a font size or a color

Suppose you have a CSS variable for a size or color, like this.

Example

<div class="text-[var(--my-value)]">
    This text uses a CSS variable.
</div>

In this example, --my-value could be used for various purposes like font size or color.

To clarify what var(--my-value) should be used for, you can specify the type explicitly. This helps Tailwind understand exactly how to apply the CSS variable.

If --my-value is meant to be a font size, or if --my-value is intended to be a color, then you should use it in this way.

Example

<!-- Font size using CSS variable -->
<div class="text-[length:var(--font-size)]">
    This text uses a CSS variable for font size.
</div>

<!-- Color using CSS variable -->
<div class="text-[color:var(--text-color)]">
    This text uses a CSS variable for color.
</div>

Using CSS and @layer

When using Tailwind CSS, you might need custom styles not covered by its utilities. Use the @layer directive to add these styles into Tailwind's system for proper ordering and optimization.

For simple custom CSS, you can just add it directly to your stylesheet.

Example

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

.custom-button {
    background-color: #4a90e2; /* Custom background color */
    border-radius: 12px;      /* Custom border radius */
    color: white;              /* Custom text color */
    padding: 10px 20px;        /* Custom padding */
    text-align: center;        /* Center text */
}

For more control, use the @layer directive to add custom styles to Tailwind's base, components, and utilities layers. This helps your styles fit well with Tailwind's existing system.

Example

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

@layer components {
    .custom-button {
        background-color: #4a90e2; /* Custom background color */
        border-radius: 12px;      /* Custom border radius */
        color: white;              /* Custom text color */
        padding: 10px 20px;        /* Custom padding */
        text-align: center;        /* Center text */
        box-shadow: 0 4px 8px rgba(0,0,0,0.2); /* Custom shadow */
        font-size: 16px;           /* Custom font size */
    }
}

Why does Tailwind group styles into layers?

Tailwind groups styles into layers to manage how they interact and which ones take priority. This approach helps prevent conflicts and ensures that styles are applied in a consistent and orderly manner.

Example

.header {
    font-size: 20px;
    
    }
    
.text-large {
    font-size: 24px;
    
    }

If both styles are used together.

Example

<h1 class="header text-large">Hello World</h1>

The text will be 24px because .text-large comes after .header, so it takes precedence.

Tailwind organizes styles into three layers:

  • Base Layer: Applies default styles that set up basic look and feel, like fonts and colors.
  • Components Layer: Adds styles for specific elements, such as a button, that you can easily reuse.
  • Utilities Layer: Includes small, single-purpose styles that can override anything from the other layers for precise design changes.

Being clear about how styles interact makes them easier to manage. The @layer directive helps you control the final order of styles while allowing you to organize your code as you like.

The @layer directive in Tailwind CSS allows you to add custom styles to Tailwind's existing layers. It keeps your styles organized, works well with Tailwind's utilities, and supports features like modifiers and tree-shaking for better performance.

Adding Base Styles in Tailwind CSS

To set default styles like text color or background color for your page in Tailwind CSS, simply add classes directly in your <html> or <body> elements.

Example

<!DOCTYPE html>
<html lang="en">
<head> 
    <script src="https://cdn.tailwindcss.com"></script> 
</head> 

<body class="p-6">
    <header class="bg-blue-500 text-white p-4 rounded">
        <h1 class="text-3xl font-semibold">My Website</h1>
    </header>
    <main class="mt-6">
        <h2 class="text-2xl font-medium mb-4">Introduction</h2>
        <p class="text-base leading-relaxed">
            This is a sample page showing custom base styles. 
            The text color is set to a dark gray, the background
            is white, and the font is sans-serif for a modern look.
        </p>
    </main>
</body>
  
</html>

This approach keeps your base styles directly in your markup, making them more visible and accessible.

If you need to apply your own custom styles to specific HTML elements, you can use Tailwind's @layer directive to include them in Tailwind's base layer.

Example

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

@layer base {
    h1 {
      @apply text-3xl font-bold;
    }
    h2 {
      @apply text-xl font-semibold;
    }
    p {
      @apply text-base leading-relaxed;
    }
}

These methods keep your base styles consistent and make them easy to adjust or expand. Use the theme function or @apply directive to include values from your theme in your custom base styles.

Adding component classes

Use the components layer for adding more complex classes to your project while still allowing for overrides with utility classes.

Traditionally, you might include classes like modal, alert, or dropdown in this category.

Example

  /* main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
    .modal {
      background-color: theme('colors.gray.800');
      border-radius: theme('borderRadius.md');
      padding: theme('spacing.4');
      box-shadow: theme('boxShadow.lg');
    }
    /* ... */
}

By defining component classes in the components layer, you can still use utility classes to adjust them as needed.

Example

<!-- Modal with no shadow -->
<div class="modal shadow-none">
    <!-- ... -->
</div>

In Tailwind, you might find that you use these component classes less frequently than expected. For tips on how to reuse styles effectively, check out our guide on Reusing Styles.

The component layer is ideal for adding custom styles to the third-party components you use.

Example

/* main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
    .custom-button {
      @apply bg-blue-500 text-white rounded-lg py-2 px-4;
    }
    .custom-input {
      @apply border border-gray-300 rounded-lg p-2;
    }
    .custom-card {
      @apply shadow-lg p-4 rounded-md;
    }
    /* ... */
}

Use the theme function or @apply directive to incorporate values from your theme into these custom styles.

Adding custom utilities

To add your own custom utility classes, use the utilities layer.

Example

    /* main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer utilities {
    .text-clip {
      text-overflow: clip;
    }
}

This is helpful for adding CSS features that Tailwind doesn't cover by default.

Using modifiers with custom CSS

Custom styles added with @layer will automatically support Tailwind's modifier syntax for things like hover states and responsive design.

Example

    /* main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer utilities {
    .content-auto {
      content-visibility: auto;
    }
}

Example

  <!-- HTML -->
<div class="lg:dark:content-auto">
    <!-- ... -->
</div>

You can find more details on how these modifiers work in the Hover, Focus, and Other States documentation.

Removing unused custom CSS

Custom styles you add to the base, components, or utilities layers will only appear in your final CSS if they are used in your HTML.

Example

/* main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
    /* This will only be included if used in your HTML */
    .alert-box {
      /* ... */
    }
}

To ensure certain custom CSS is always included, add it directly to your stylesheet without using the @layer directive.

Example

/* main.css */
@tailwind base;
@tailwind components;

/* This will always be included in your final CSS */
.alert-box {
  /* ... */
}

@tailwind utilities;

Remember to position yourself wisely to get the right results. For example, we have placed the .alert-box class before @tailwind utilities so that utility classes can still override it if necessary.

Using multiple CSS files

When working with multiple CSS files, make sure to combine them into a single stylesheet before processing with Tailwind. Otherwise, you might get errors about @layer and @tailwind directives.

You can combine files easily using the postcss-import plugin.

// postcss.config.js
module.exports = {
    plugins: {
        'postcss-import': {},
        tailwindcss: {},
        autoprefixer: {},
    }
}

For more information, refer to our documentation on build-time imports.

Layers and per-component CSS

In component frameworks like Vue and Svelte, you can add styles directly within a <style> block in each component file.

You can use features like @apply and theme inside component styles, but the @layer directive will not function properly. Instead, you'll encounter an error indicating that @layer is being used without a corresponding @tailwind directive.

So, try not to use @layer within component styles.

Example

<!-- Modal.vue -->
<template>
    <div class="modal">
      <slot></slot>
    </div>
</template>

<style>
    /* This will trigger an error because @layer isn't supported here */
    @layer components {
        .modal {
          background-color: theme('colors.gray.800');
          border-radius: theme('borderRadius.md');
          padding: theme('spacing.4');
        }
    }
</style>

This happens because frameworks like Vue and Svelte process each <style> block separately. They run PostCSS plugins on each block independently, so Tailwind cannot combine styles from different components or handle @layer correctly. Each <style> block is processed in isolation, with no awareness of the others.

One solution is to avoid using @layer inside component styles.

Apply styles directly without using @layer.

Example

<!-- Modal.vue -->
<template>
    <div class="modal">
        <slot></slot>
    </div>
</template>

<style>
    /* This will trigger an error because @layer isn't supported here */
    .modal {
        background-color: theme('colors.gray.800');
        border-radius: theme('borderRadius.md');
        padding: theme('spacing.4');
    }
</style>

By avoiding @layer in component styles, you'll lose control over the precedence of your styles, which is a limitation due to how these tools function.

We recommend using Tailwind as it's designed to be used: apply Tailwind's utility classes directly in your HTML. This approach ensures you avoid issues with style processing and make the most of Tailwind's capabilities.

Use Tailwind's utility classes instead of writing custom component styles.

Example

<!-- Modal.vue -->
<template>
    <div class="bg-gray-800 rounded-md p-4">
        <slot></slot>
    </div>
</template>

This way, you avoid style processing issues and take full advantage of Tailwind's utility classes.

Writing plugins

Instead of using a separate CSS file for custom styles, you can extend Tailwind by writing your own plugins.

tailwind.config.js

Example

const plugin = require('tailwindcss/plugin')

module.exports = {
    // ...
    plugins: [
      plugin(function ({ addBase, addComponents, addUtilities, theme }) {
        addBase({
          'p': {
            lineHeight: theme('lineHeight.relaxed'),
          },
          'a': {
            color: theme('colors.blue.600'),
            textDecoration: 'none',
          },
        })
        addComponents({
          '.alert': {
            backgroundColor: theme('colors.red.100'),
            border: `1px solid ${theme('colors.red.300')}`,
            borderRadius: theme('borderRadius.sm'),
            padding: theme('spacing.4'),
          }
        })
        addUtilities({
          '.text-clip': {
            textOverflow: 'clip',
          }
        })
      })
    ]
}

This method allows you to add custom styles and utilities directly in your Tailwind configuration file, making your workflow easier and keeping styles organized. For more details on creating your own plugins, check out the Plugins documentation.