Tailwind 4 Plugin Migration

Feb 04, 2025 (287 views)

It's been awhile since I last updated this site. I decided to take on the task of migrating not only Tailwind to version 4, but updating/migrating a slew of other Nuxt modules & packages.

Tailwind 4 has provided a new way of creating plugins using the @utility directive within your stylesheet, instead of using javascript.

You are still able to create plugins using javascript in v4, but the process has changed slightly. See Tailwind 4 Legacy Plugins.

Here are a few examples of plugins I created/migrated in Tailwind 4:

Tailwind 3 Plugin

This plugin takes in a dynamic value and sets the aspect ratio of an element. It also has support for older browsers that don't support the aspect-ratio property.

aspect-ratio.plugin.js
const aspectRatio = ({ matchUtilities, theme }) =>
  matchUtilities(
    {
      aspect: (value) => ({
        '@supports (aspect-ratio: 1 / 1)': {
          aspectRatio: value,
        },
        '@supports not (aspect-ratio: 1 / 1)': {
          '&::before': {
            content: '""',
            float: 'left',
            paddingTop: `calc(100% / (${value}))`,
          },
          '&::after': {
            clear: 'left',
            content: '""',
            display: 'block',
          },
        },
      }),
    },
    { values: theme('aspectRatio') }
  );

This is how you would add this plugin to your tailwind.config.js file under plugins:

tailwind.config.js
{
  plugins: [({ matchUtilities, theme }) => {
    aspectRatio({ matchUtilities, theme });
  }]
}

Tailwind 4 Utility

We will now convert the above plugin to a Tailwind 4 utility using the @utility directive. We use the --value() function to get the value. In our case below, we need the value to be fraction.

This will match utilities like aspect-[1/1] and aspect-[16/9].

styles.css
@utility aspect-* {
  @supports (aspect-ratio: 1 / 1) {
    aspect-ratio: --value(--aspect-ratio-*, ratio, [ratio]);
  }

  @supports not (aspect-ratio: 1 / 1) {
    &::before {
      content: '';
      float: left;
      padding-top: calc(100% / (--value(--aspect-ratio-*, ratio, [ratio])));
    }

    &::after {
      clear: left;
      content: '';
      display: block;
    }
  }
}

Dynamic Header Utility

This utility allows me set default styles for my headers, but also allows me replicate those header styles on other elements. I'll also be adding a modifier for font weight.

  1. I'll start off by defining theme values for headers. The --spacing function generates a spacing based on the value passed in. We will be restricting the utility for headers 1-6.
styles.css
@theme inline {
  --header-1: --spacing(7);
  --header-2: --spacing(6.5);
  --header-3: --spacing(6);
  --header-4: --spacing(5);
  --header-5: --spacing(4.5);
  --header-6: --spacing(4);
}
  1. Next, we will create the utility with a font-weight modifier
  2. This will match utilities like header-1, and header-2.
  3. The modifier allows me to pass in a theme value for font-weight or a custom value.
  4. With a modifier, I could use header-1/semibold and header-3/normal to set the font weight.
styles.css
@utility header-* {
  font-size: --value(--header-*);
  font-weight: --modifier(--font-weight-*, [length], [*]);
}

To Be Continued...