在 TailwindCss 中动态构建类名

Wes*_*nse 81 reactjs next.js tailwind-css

我目前正在使用 TailwindCss 为我的下一个项目构建一个组件库,我在处理 Button 组件时遇到了一个小问题。

我传入一个类似于'primary'或 的道具'secondary',它与我在中指定的颜色相匹配,tailwind.config.js然后我想使用Template literals如下方式将其分配给按钮组件:bg-${color}-500

<button
    className={`
    w-40 rounded-lg p-3 m-2 font-bold transition-all duration-100 border-2 active:scale-[0.98]
    bg-${color}-500 `}
    onClick={onClick}
    type="button"
    tabIndex={0}
  >
    {children}
</button>
Run Code Online (Sandbox Code Playgroud)

类名在浏览器中显示得很好,它显示bg-primary-500在 DOM 中,但不显示在“应用的样式”选项卡中。

在此输入图像描述

主题配置如下:

  theme: {
    extend: {
      colors: {
        primary: {
          500: '#B76B3F',
        },
        secondary: {
          500: '#344055',
        },
      },
    },
  },
Run Code Online (Sandbox Code Playgroud)

但它不应用任何样式。如果我只是手动添加bg-primary-500它工作正常。

老实说,我只是想知道这是否是因为 JIT 编译器没有选择动态类名,或者我是否做错了什么(或者这不是使用 tailWind 的方式)。

欢迎任何帮助,提前致谢!

Wes*_*nse 38

所以在发现这种工作方式不推荐并且JIT也不支持之后(感谢慷慨的评论者)。我已将方法更改为更加基于“配置”的方法。

基本上,我使用不同 props 的基本配置定义一个 const 并将它们应用到组件。这需要更多的维护工作,但它可以完成工作。

这是配置的示例。(目前无需打字)并进行一些更好的重构,但您会明白的。

const buttonConfig = {
  // Colors
  primary: {
    bgColor: 'bg-primary-500',
    color: 'text-white',
    outline:
      'border-primary-500 text-primary-500 bg-opacity-0 hover:bg-opacity-10',
  },
  secondary: {
    bgColor: 'bg-secondary-500',
    color: 'text-white',
    outline:
      'border-secondary-500 text-secondary-500 bg-opacity-0 hover:bg-opacity-10',
  },

  // Sizes
  small: 'px-3 py-2',
  medium: 'px-4 py-2',
  large: 'px-5 py-2',
};
Run Code Online (Sandbox Code Playgroud)

然后我就这样应用样式:

  <motion.button
    whileTap={{ scale: 0.98 }}
    className={`
    rounded-lg font-bold transition-all duration-100 border-2 focus:outline-none
    ${buttonConfig[size]}
    ${outlined && buttonConfig[color].outline}
    ${buttonConfig[color].bgColor} ${buttonConfig[color].color}`}
    onClick={onClick}
    type="button"
    tabIndex={0}
  >
    {children}
  </motion.button>
Run Code Online (Sandbox Code Playgroud)

  • 甚至可以将 tailwind 类(您希望包含以供动态使用)作为注释添加到代码中的某处。允许使用 `bg-${color}-100 text-${color}-500` 只要您在注释中为您想要包含的每种颜色提及 `bg-accent-100 text-accent-500` 即可。 (12认同)

tne*_*e12 26

不推荐这种编写 Tailwind CSS 类的方式。即使JIT 模式也不支持它,引用 Tailwind CSS 文档:“ Tailwind 不\xe2\x80\x99t 包含任何类型的客户端运行时,因此类名需要在构建时静态提取,并且可以\ xe2\x80\x99t 取决于客户端上更改的任何类型的任意动态值

\n


sil*_*ver 18

这可能有点晚了,但对于那些碰上这个帖子的人来说。

对此最简单的解释是;

除非您为动态类名称配置了安全列表,否则动态类名称不起作用,

但是,动态类只要是完整的顺风类名称就可以正常工作。

它在这里说明

这行不通

<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
Run Code Online (Sandbox Code Playgroud)

但这是有效的

<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
Run Code Online (Sandbox Code Playgroud)

它的状态;

只要您始终在代码中使用完整的类名,Tailwind 每次都会完美生成所有 CSS。

较长的解释;

module.exports.contentTailwind 将扫描内部指定的所有文件tailwind.config.js并查找 tailwind 类,它甚至不必位于类属性中,甚至可以添加在注释行中,只要完整的类名存在于该文件和类名中即可不是动态构造的;Tailwind 将拉动该级别的造型,

因此,在您的情况下,您所要做的就是在该文件中输入动态类的所有可能值的完整类名,如下所示

<button className={ color === 'primary' ? 'bg-primary-500' : 'bg-secondary-500'}>
    {children}
</button>
Run Code Online (Sandbox Code Playgroud)

或者我更喜欢的方法

<!-- bg-primary-500 bg-secondary-500 -->
<button className={`bg-${color}-500 `}>
    {children}
</button>
Run Code Online (Sandbox Code Playgroud)

这是另一个例子,虽然是 Vue,但对于任何 JS 框架来说,这个想法都是一样的

<template>
    <div :class="`bg-${color}-100 border-${color}-500 text-${color}-700 border-l-4 p-4`" role="alert">
        test
    </div>
</template>
<script>
    /* all supported classes for color props 
    bg-red-100 border-red-500 text-red-700
    bg-orange-100 border-orange-500 text-orange-700
    bg-green-100 border-green-500 text-green-700
    bg-blue-100 border-blue-500 text-blue-700
    */
    export default {
        name: 'Alert',
        props: {
            color: {type: String, default: 'red'}
        }
    }
</script>
Run Code Online (Sandbox Code Playgroud)

结果就是这样

<Alert color="red"></Alert> <!-- this will have color related styling-->
<Alert color="orange"></Alert> <!-- this will have color related styling-->
<Alert color="green"></Alert> <!-- this will have color related styling-->
<Alert color="blue"></Alert> <!-- this will have color related styling-->
<Alert color="purple"></Alert> <!-- this will NOT have color related styling as the generated classes are not pre-specified inside the file -->
Run Code Online (Sandbox Code Playgroud)


A. *_*zek 12

编辑:2022 年更好的实施 - /sf/answers/5114057161/

Tailwind CSS 不支持动态类名称(请参阅此处)。然而,仍然有一种方法可以实现这一点。我需要在 Vue3 应用程序中使用动态构建类名。请参阅下面的代码示例。

构建后,Tailwind 会扫描您的应用程序以查找正在使用的类,并自动清除所有其他类(请参阅此处)。然而,有一个savelist功能可以用来从清除中排除类——也就是说,它们总是会进入生产环境。

我在下面创建了一个示例代码,我在生产中使用它。它结合了每种颜色和每种色调 ( colorValues array)。

这个类名数组被传递到safelist. 请注意,通过实现此功能,您可以将更多 css 数据传送到生产环境,并传送您可能永远不会使用的 css 类。

const colors = require('./node_modules/tailwindcss/colors');
const colorSaveList = [];
const extendedColors = {};
const colorValues = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];

for (const key in colors) {
  

  // To avoid tailWind "Color deprecated" warning
  if (!['lightBlue', 'warmGray', 'trueGray', 'coolGray',  'blueGray'].includes(key))
  {
    extendedColors[key] = colors[key];
    for(const colorValue in colorValues) {
       colorSaveList.push(`text-${key}-${colorValue}`);
       colorSaveList.push(`bg-${key}-${colorValue}`);
    }
  }
}


module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}"
  ],
  safelist: colorSaveList,
  theme: {
   extend: {
      colors: extendedColors
   }
  },
  plugins: [
    require('tailwind-scrollbar'),
  ]

}
Run Code Online (Sandbox Code Playgroud)


mbd*_*vis 8

如果有人在 2022 年遇到 - 我接受了 A. Mr\xc3\xb3zek\ 的答案,并进行了一些调整,以避免出现已弃用的警告和迭代非对象调色板的问题。

\n
const tailwindColors = require("./node_modules/tailwindcss/colors")\nconst colorSafeList = []\n\n// Skip these to avoid a load of deprecated warnings when tailwind starts up\nconst deprecated = ["lightBlue", "warmGray", "trueGray", "coolGray", "blueGray"]\n\nfor (const colorName in tailwindColors) {\n  if (deprecated.includes(colorName)) {\n    continue\n  }\n\n  const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]\n\n  const pallette = tailwindColors[colorName]\n\n  if (typeof pallette === "object") {\n    shades.forEach((shade) => {\n      if (shade in pallette) {\n        colorSafeList.push(`text-${colorName}-${shade}`)\n        colorSafeList.push(`bg-${colorName}-${shade}`)\n      }\n    })\n  }\n}\n\n// tailwind.config.js\nmodule.exports = {\n  safelist: colorSafeList,\n  content: ["{pages,app}/**/*.{js,ts,jsx,tsx}"],\n  theme: {\n    extend: {\n      colors: tailwindColors,\n    },\n  },\n  plugins: [],\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • 如我错了请纠正我。但是,如果 colorName 包含在已弃用的数组中,那么在检查时,您不应该在 for 循环中使用 **continue** 而不是 **break** 吗?否则,在找到已弃用的颜色时,您将打破循环,并且不会再将任何颜色添加到 tailwindColors 数组中。 (2认同)

Ble*_*ing 6

JIT对于使用的顺风模式或 v3 JIT,您必须确保导出对象样式的文件包含在 中的内容选项中tailwind.config.js,例如

 content: ["./src/styles/**/*.{html,js}"], 
Run Code Online (Sandbox Code Playgroud)