🐌

tailwindcssで動的クラスを作るときにハマった

2024/04/30に公開

概要

Vue3やReactでコンポーネントを作っている際に、動的にtailwindcssのクラスを生成するためコードを書いたところ、例としてroundedの場合次のような挙動をしました。

  • rounded-mdとした場合正常に機能する。
  • rounded-smfullとした場合にスタイルが適用されない。

tailwindcssのスタイルが部分的に機能したりしなかったりするような挙動です。

バグってた時のソース
export const generateTailwindRoundedClass = (value: string, defaultValue: string) => {
  const allowedValues = ['none', 'sm', 'md', 'lg', 'xl' , 'full'];
  return allowedValues.includes(value) ? `rounded-${value}` : `rounded-${defaultValue}`;
}

原因

要約:ここに書いてあるママ
https://tailwindcss.com/docs/content-configuration#dynamic-class-names
tailwindcssでは、ソースコード内のcompleteでunbrokenなクラスのみを探すようにできています。
従って、上記のコードのrounded-${value}のような記述では、最初に記述されていた値rounded-mdのみ探すことに成功し、それ以外は失敗するため、あるパターンは機能するけど他のクラスは機能しない。。。といった挙動になるわけです。

解決方法

公式で言われている通り、完全なクラス名にする。

definition.ts
export const generateTailwindRoundedClass = {
  none: "rounded-none",
  sm: "rounded-sm",
  md: "rounded-md",
  lg: "rounded-lg",
  xl: "rounded-xl",
  full: "rounded-full",
}
Component.vue
<script setup lang="ts">
import { generateTailwindRoundedClass } from '../../definition';

const defaultClass = { //コンポーネントごとにdefaultの値を設定する
  rounded: 'rounded-md',
}

// 存在しない値の場合はデフォルト値を返すようにして安全にしている
const roundedClass = generateTailwindRoundedClass[props.rounded as keyof typeof generateTailwindRoundedClass] || defaultClass.rounded

Discussion