Using Tailwind CSS

Tailwind CSS is a CSS framework and design system based on Utility Class, which can quickly add common styles to components, and support flexible extension of theme styles.

Modern.js Module supports developing component styles using Tailwind CSS.

Enabling Tailwind CSS

To use Tailwind CSS in Modern.js Module, you can follow the steps below:

  1. Run pnpm run new in the root directory of your project and make the following selections:
? Please select the operation you want: Enable features
? Please select the feature name: Enable Tailwind CSS

After successful initialization, you will see that the package.json has added dependencies for tailwindcss and @modern-js/plugin-tailwindcss.

  1. Register the Tailwind plugin in modern.config.ts:
modern.config.ts
import { tailwindcssPlugin } from '@modern-js/plugin-tailwindcss';

export default defineConfig({
  plugins: [..., tailwindcssPlugin()],
});
  1. Create a index.css file and add the following code:
index.css
/* base and components are optional, please add as appropriate */
@tailwind base;
@tailwind components;
@tailwind utilities;
INFO

Depending on your needs, you can selectively import the CSS styles provided by Tailwind CSS. Please refer to the @tailwind documentation for detailed usage of the @tailwind directive.

  1. Import the index.css file, for example, add the following code in the root component src/index.jsx:
import './index.css';
  1. Now you can use the Utility Classes provided by Tailwind CSS in your components:
const Hello = () => (
  <div className="h-12 w-48">
    <p className="text-xl font-medium text-black">hello world</p>
  </div>
);

Configuring Tailwind CSS

In Modern.js Module, you have two ways to configure Tailwind CSS:

  1. Using the tailwind.config.{ts,js} file, which follows the official usage of Tailwind CSS. Please refer to "Tailwind CSS - Configuration" for more details.
tailwind.config.ts
import type { Config } from 'tailwindcss';

export default {
  content: ['./src/**/*.{js,jsx,ts,tsx}'],
} as Config;
TIP

Please upgrade Modern.js to version >= 2.33.0 to support automatic reading of tailwind.config.{ts,js} files.

  1. Using the style.tailwindcss configuration option. This is the old way of configuring Tailwind CSS, and we recommend using the tailwind.config.{ts,js} file for configuration.
modern.config.ts
export default {
  tools: {
    tailwindcss: {
      content: ['./src/**/*.{js,jsx,ts,tsx}'],
    },
  },
};

If you are using both the tailwind.config.{ts,js} file and style.tailwindcss option, the configuration defined in style.tailwindcss will take precedence and override the content defined in tailwind.config.{ts,js}.

Tailwind CSS Autocomplete

Tailwind CSS provides an official extension called Tailwind CSS IntelliSense for autocompletion of Tailwind CSS class names, CSS functions, and directives in VS Code.

You can follow the steps below to enable the autocomplete feature:

  1. Install the Tailwind CSS IntelliSense extension in VS Code.
  2. If the root directory of your project does not have a tailwind.config.{ts,js} file, you need to create one and write the Tailwind CSS configuration for your current project. Otherwise, the IDE plugin will not work correctly.

Build Modes

When using Tailwind CSS, please note that there are significant differences between the bundle and bundleless modes in terms of the build artifacts.

TIP

For definitions of bundle and bundleless, please refer to the "In-depth understanding of build".

Bundle Mode

In Bundle mode, a separate CSS file is generated, and the JS output does not automatically reference the CSS output file.

  • Source code:
./src/index.tsx
import './index.css';

export default () => {
  return <div className="bg-black">hello world</div>;
};
  • Output code:
./dist/es/index.js
// src/index.tsx
import { jsx } from 'react/jsx-runtime';
var src_default = () => {
  return /* @__PURE__ */ jsx('div', {
    className: 'bg-black',
    children: 'hello world',
  });
};
export { src_default as default };
./dist/es/index.css
.bg-black {
  --tw-bg-opacity: 1;
  background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
/** some more... */

If you need to inject styles into the JS artifact, you can enable the style.inject option.

If you haven't enabled style.inject, you can also let users manually import the CSS file:

import 'your-package/dist/es/index.css';

Bundleless Mode

In bundleless mode, the CSS file is automatically imported in the artifact code without the need for additional processing.

  • Output code:
./dist/es/index.js
import { jsx as _jsx } from 'react/jsx-runtime';
import './index.css';
export default () =>
  /* @__PURE__ */ _jsx('div', {
    className: 'bg-black',
    children: 'hello world',
  });

Class Name Prefix

You can add a class name prefix using the prefix option provided by Tailwind CSS. This helps avoid potential class name conflicts, such as when different versions of Tailwind CSS are used in different parts of an application or module.

For example, you can add the foo- prefix using the prefix option in tailwind.config.js:

tailwind.config.js
module.exports = {
  prefix: 'foo-',
};
  • Source Code:
./src/index.tsx
import './index.css';

export default () => {
  return <div className="foo-bg-black">hello world</div>;
};
  • Output Code:
./dist/es/index.css
.foo-bg-black {
  --tw-bg-opacity: 1;
  background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
/** some more... */

Usage Guide

Here are some usage examples of Tailwind CSS.

HTML Class Names

Tailwind CSS supports adding styles to HTML tags through class names. When using HTML class names, please note that the corresponding CSS styles of Tailwind CSS must be imported in advance.

./src/index.tsx
import './index.css';

export default () => {
  return <div className="bg-black">hello world</div>;
};

Generated styles (after bundling):

./dist/es/index.css
.bg-black {
  --tw-bg-opacity: 1;
  background-color: rgba(0, 0, 0, var(--tw-bg-opacity));
}
/** some more... */

@apply

Tailwind CSS provides the @apply directive, which allows us to inline the styles provided by Tailwind CSS into our own styles.

@apply can be used in CSS, Less, and Sass.

.btn {
  @apply font-bold py-2 px-4 rounded;
}

However, there are some considerations when using it with Less and Sass:

Sass

When using Tailwind with Sass and there is an !important after @apply, interpolation should be used to ensure Sass compiles correctly.

  • Won't work as expected:
.alert {
  @apply bg-red-500 !important;
}
  • Will work as expected:
.alert {
  @apply bg-red-500 #{!important};
}

Less

When using Tailwind with Less, you cannot nest Tailwind's @screen directive.

  • Won't work as expected:
.card {
  @apply rounded-none;

  @screen sm {
    @apply rounded-lg;
  }
}
  • Instead, use regular media queries and the theme() function to reference your screen sizes or simply avoid nesting your @screen directive.
Method 1
// Use a regular media query and theme()
.card {
  @apply rounded-none;

  @media (min-width: theme('screens.sm')) {
    @apply rounded-lg;
  }
}
Method 2
// Use the @screen directive at the top-level
.card {
  @apply rounded-none;

  @media (min-width: theme('screens.sm')) {
    @apply rounded-lg;
  }
}

About designSystem config

designSystem is a deprecated configuration option in Modern.js Module.

Starting from Modern.js Module version 2.33.0, you can use the theme configuration option of Tailwind CSS as a replacement for designSystem. It is no longer necessary to split the theme configuration and set it on designSystem.

  • Previous usage:
modern.config.ts
const { theme, ...rest } = tailwindConfig;

export default {
  style: {
    tailwindcss: rest,
  },
  designSystem: theme,
};
  • Current usage:
modern.config.ts
export default {
  style: {
    tailwindcss: tailwindConfig,
  },
};