如果在 className 中使用变量,则 React/Next.js 中的 Tailwind 不会为 text-*xl 类生成 css

Posted

技术标签:

【中文标题】如果在 className 中使用变量,则 React/Next.js 中的 Tailwind 不会为 text-*xl 类生成 css【英文标题】:Tailwind in React/Next.js doesn't generate css for text-*xl classes if variable is used in className 【发布时间】:2021-11-07 06:01:02 【问题描述】:

我想使用 Tailwind 创建 React Title 组件,您可以在其中传递级别(H1-H6 或如果为空则将其设为 DIV)和传递大小(从 text-xl 到 text-9xl 的 1-9)。

例如,我可以有这样的可重用组件:

// Reusable component:
<Title level=2 size=4>Test title</Title>
// Which renders to:
<h2 className="text-4xl">Test title</h2>

我可以在 Inspector 中看到这些类,我还可以看到没有为项目生成 .font-4xl css。所以标题保持默认字体大小。 但是,如果我添加任何测试文本,例如&lt;div class="text-4xl"&gt;test&lt;/div&gt;,那么它将生成 css 并将其应用于组件。可以对所有 9 种尺寸重复此操作。

有没有办法让 Tailwind 仅在使用时生成 css(非常适合最小的文件大小),但同时也为组件提供某种干净的代码?

现在,我的想法是让所有常见的类都应用在可重用的 Title 组件中,但总是在使用它时添加所需的大小 (text-*xl)。

const Title = ( children, className, style, level, size ) => 
  const commonClass = 'font-extrabold uppercase mb-4';

  const fontSize = size ? `text-$sizexl` : `text-$levelxl`;

  switch (level) 
    case 1:
      return (
        <h1 className=`$fontSize $commonClass` style=style>
          children
        </h1>
      );
    case 2:
      return (
        <h2 className=`$fontSize $commonClass` style=style>
          children
        </h2>
      );
    case 3:
      return (
        <h3 className=`$fontSize $commonClass` style=style>
          children
        </h3>
      );
    case 4:
      return (
        <h4 className=`$fontSize $commonClass` style=style>
          children
        </h4>
      );
    case 5:
      return (
        <h5 className=`$fontSize $commonClass` style=style>
          children
        </h5>
      );
    case 6:
      return (
        <h6 className=`$fontSize $commonClass` style=style>
          children
        </h6>
      );
    default:
      return (
        <div className=`$fontSize $commonClass` style=style>
          children
        </div>
      );
  
;

export default Title;

【问题讨论】:

试试styled-components,基本上你需要一个本地化的css。这通常被称为 css-in-js。搜索并选择任何一个开放的图书馆。 【参考方案1】:

来自 JIT mode 上动态值的 Tailwind 文档

动态值

请注意,您仍然需要编写可清除的 html 使用任意值,并且您的类需要完整存在 供 Tailwind 正确检测的字符串。

不要使用字符串连接来创建类名

<div className=`mt-[$size === 'lg' ? '22px' : '17px' ]`></div>

Tailwind 不包含任何类型的客户端运行时,因此类 名称需要在构建时静态提取,并且不能 取决于任何类型的任意动态值,这些值随 客户。在这些情况下使用内联样式,或结合 Tailwind 如果对您有意义,则使用 E​​motion 之类的 CSS-in-JS 库 项目

所以你应该使用类似的东西,或者 switchif 语句可以正常工作。

const sizeArg = size ? size : level;
const fontSize = textSize === 1 ? 'text-1xl' : (sizeArg === 2 ? 'text-2xl' : (...))

【讨论】:

您的带有链式三元运算符的示例工作得非常好,并且具有更漂亮的自动格式化,它甚至看起来干净易读。非常感谢!正如您所提到的,它是由 JIT 模式和字符串连接引起的。我从不使用 JIT 模式的旧项目中复制了我的 Title 组件,它基本上引入了这个问题,但我很高兴现在我明白了哪里出了问题。

以上是关于如果在 className 中使用变量,则 React/Next.js 中的 Tailwind 不会为 text-*xl 类生成 css的主要内容,如果未能解决你的问题,请参考以下文章

CSS 不使用嵌套的 className 规则

在 className `if` 语句中反应`or` 条件

使用 className=styles.nameOfClass 时出现“未解析的变量”

vue中点击div里的当前元素添加class删除其他兄弟元素的class?

zepto源码--filtered, contains,funcArg,setAttribute,className,deserializeVale--学习笔记

Tailwind css - 使用 className 自定义间距值作为 tailwind 配置的变量