使用 Tailwind CSS

Tailwind CSS 是一个以 Utility Class 为基础的 CSS 框架和设计系统,可以快速地为组件添加常用样式,同时支持主题样式的灵活扩展。

Modern.js Module 支持使用 Tailwind CSS 开发组件样式。

启用 Tailwind CSS

在 Modern.js Module 中使用 Tailwind CSS,你只需要按照以下步骤操作:

  1. 在项目根目录下执行 pnpm run new,按照如下进行选择:
? 请选择你想要的操作 启用可选功能
? 请选择功能名称 启用 「Tailwind CSS」 支持

成功开启后,你会看到 package.json 中新增了 tailwindcss@modern-js/plugin-tailwindcss 依赖。

  1. modern.config.ts 中注册 Tailwind 插件:
modern.config.ts
import { tailwindcssPlugin } from '@modern-js/plugin-tailwindcss';

export default defineConfig({
  plugins: [..., tailwindcssPlugin()],
});
  1. 创建 index.css 文件,添加以下代码:
index.css
/* base 和 components 是可选的,请酌情添加 */
@tailwind base;
@tailwind components;
@tailwind utilities;
INFO

根据需求不同,你可以选择性地导入 Tailwind CSS 提供的 CSS 样式。请参考 @tailwind 文档 来了解 @tailwind 指令的详细用法。

  1. 引用 index.css 文件,比如在入口的 src/index.jsx 文件添加如下代码:
import './index.css';
  1. 然后即可在各个组件中使用 Tailwind CSS 提供的 Utility Class 了:
const Hello = () => (
  <div className="h-12 w-48">
    <p className="text-xl font-medium text-black">hello world</p>
  </div>
);

配置 Tailwind CSS

在 Modern.js Module 中,你有两种方式来配置 Tailwind CSS:

  1. 使用 tailwind.config.{ts,js} 文件,该用法与 Tailwind CSS 的官方用法一致,请参考 "Tailwind CSS - Configuration" 来了解更多用法。
tailwind.config.ts
import type { Config } from 'tailwindcss';

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

请升级 Modern.js Module 到 >= 2.33.0 版本,以支持自动读取 tailwind.config.{ts,js} 文件。

  1. 使用 style.tailwindcss 配置项,这是旧版本的用法,我们更推荐使用 tailwind.config.{ts,js} 文件进行配置。
modern.config.ts
export default {
  style: {
    tailwindcss: {
      content: ['./src/**/*.{js,jsx,ts,tsx}'],
    },
  },
};

如果你同时使用了 tailwind.config.{ts,js} 文件和 style.tailwindcss 选项,那么 style.tailwindcss 定义的配置会优先生效,并覆盖 tailwind.config.{ts,js} 中定义的内容。

Tailwind CSS 自动补全

Tailwind CSS 官方提供了 Tailwind CSS IntelliSense 插件,用于在 VS Code 中自动补全 Tailwind CSS 的 class names、CSS functions 和 directives。

你可以参考以下步骤来启动自动补全功能:

  1. 在 VS Code 中安装 Tailwind CSS IntelliSense 插件。
  2. 如果项目的根目录没有 tailwind.config.{ts,js} 文件,那么你需要创建该文件,并写入当前项目的 Tailwind CSS 配置,否则 IDE 插件将无法正确生效。

构建模式

在使用 Tailwind CSS 时,请注意构建产物在 bundle 和 bundleless 两种模式下会有很大区别。

TIP

关于 bundle 和 bundleless 的定义,可以查看 「深入理解构建」

Bundle 模式

在 Bundle 模式下,会生成一份单独的产物 CSS 文件,并且 JS 产物不会自动引用产物 CSS 文件。

  • 源代码:
./src/index.tsx
import './index.css';

export default () => {
  return <div className="bg-black">hello world</div>;
};
  • 产物代码:
./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... */

如果你需要将样式注入 JS 产物中,可以开启 style.inject 选项。

如果你没有开启 style.inject,那么也可以让用户手动引用产物 CSS 文件:

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

Bundleless 模式

在 Bundleless 模式下,默认会引用产物 CSS 文件,无须进行额外处理。

  • 产物代码:
./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',
  });

类名前缀

你可以通过 Tailwind CSS 提供的 prefix 选项来添加类名前缀,这样可以避免潜在的类名冲突问题(比如 App 和 Module 使用了不同版本的 Tailwind CSS)。

例如,通过 prefix 选项添加 foo- 前缀:

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

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

用法介绍

下面是一些 Tailwind CSS 的用法示例。

HTML 类名

Tailwind CSS 支持在 HTML 标签上通过类名的方式增加样式。当使用 HTML 类名的时候,请注意必须要提前导入 Tailwind CSS 相应的 CSS 样式。

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

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

样式产物(此时是 bundle 构建):

./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 提供了 @apply 指令,可以通过它将 Tailwind CSS 提供的样式内联到我们编写的样式中。

@apply 可以用于 CSS、Less、Sass 中。

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

但是使用过程中,对于 Less 和 Sass 有些情况需要注意:

Sass

当将 Tailwind 与 Sass 一起使用时,@apply 后面存在 !important 的时候,需要使用插值来让 Sass 正确编译。

  • 不能正常工作:
.alert {
  @apply bg-red-500 !important;
}
  • 能够正常工作:
.alert {
  @apply bg-red-500 #{!important};
}

Less

在与 Less 一起使用 Tailwind 时,你不能嵌套 Tailwind 的 @screen 指令。

  • 不能正常工作:
.card {
  @apply rounded-none;

  @screen sm {
    @apply rounded-lg;
  }
}
  • 相反,使用常规的媒体查询和 theme() 函数来引用你的屏幕尺寸,或者干脆不要嵌套你的 @screen 指令。
方法一
// Use a regular media query and theme()
.card {
  @apply rounded-none;

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

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

关于 designSystem 配置

designSystem 是 Modern.js Module 中废弃的配置项。

从 Modern.js Module v2.33.0 版本开始,你可以使用 Tailwind CSS 的 theme 配置项来代替 designSystem,不再需要将 theme 配置拆分并设置到 designSystem 上。

  • 旧版本用法:
modern.config.ts
const { theme, ...rest } = tailwindConfig;

export default {
  style: {
    tailwindcss: rest,
  },
  designSystem: theme,
};
  • 当前版本用法:
modern.config.ts
export default {
  style: {
    tailwindcss: tailwindConfig,
  },
};