How I manage my enormous`class` attributes in Tailwind projects

aaronmw

Aaron Wright

Posted on June 13, 2024

How I manage my enormous`class` attributes in Tailwind projects

I'm curious what sorts of workflows you might have developed for dealing with oodles and oodles of classes on a single element, often amongst many others within a single component.

I figured I'd share what I currently do, and maybe others can show me how they'd do it differently. Or maybe I can at least inspire someone else with my examples:

import { ComponentProps, useState } from 'react'
import { twMerge } from 'tailwind-merge'

// A TypeScript template literal tag function for Tailwind classes
// Usually imported from a folder of other utilities
function tw(strings: TemplateStringsArray, ...values: any[]) {
  return String.raw({ raw: strings }, ...values)
}

// Sometimes this is exported from a file of its own if things get hairy
// For even simpler components, this wouldn't even be a function
// and instead I'd just have the object itself, named `classNames` or something
function getClassNames({ someCondition = false }) {
  return {
    container: twMerge(
      someCondition &&
        `
          bg-red-400
          text-red-600
        `,
      `
        flex
        h-full
        flex-col
        items-center
        justify-center
      `,
    ),

    someSemanticallyNamedElement: tw`
      text-lg
    `,
  }
}

// Most of my components still accept a className prop,
// so I merge it with the lovely `tailwind-merge` library
export function MyComponent({
  className,
  ...otherProps
}: ComponentProps<'div'>) {
  const [someCondition, setSomeCondition] = useState(false)
  const classes = getClassNames({ someCondition })

  return (
    <div
      // ⛙ Merge the classes. The incoming classes take precedence
      // but sometimes I pass them first if I need to ensure
      // specific classes can't be overridden
      className={twMerge(classes.container, className)}
      {...otherProps}
    >
      <div className={classes.someSemanticallyNamedElement}>Hello, world!</div>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
aaronmw
Aaron Wright

Posted on June 13, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related