htmlcsstailwind-css

Drying up identical Tailwind classes


In my app I have a lot of form inputs that often use identical styling with endless classes that make my eyes bleed. Tailwind encourages to just repeat the classes but I feel like that violates dry principles and is bloating up the code. I'm searching for a way to centralize and reuse Tailwind classes

<div class="">
  <div class="flex items-center">
    <p class="text-xl w-6 text-red-600">πŸ—Ž</p>
    <h1 class="ml-4 text-gray-400">Description</h1>
  </div>
  <textarea
    oninput=" this.style.height='', this.style.height = this.scrollHeight +'px'"
    formControlName="description"
    class="ml-8 mt-1 p-2.5 w-5/6 text-sm rounded-md !outline-none focus:shadow-sm focus:ring-1 focus:ring-pink-400"
  ></textarea>
</div>

<div>
  <div class="flex items-center">
    <p class="text-xl w-6 text-red-600">πŸ—€</p>
    <h1 class="ml-4 text-gray-400">Projects</h1>
  </div>
  <textarea
    oninput=" this.style.height = this.scrollHeight +'px'"
    formControlName="projects"
    class="ml-8 mt-1 p-2.5 w-5/6 text-sm rounded-md !outline-none focus:shadow-sm focus:ring-1 focus:ring-pink-400"
  ></textarea>
</div>

Solution

  • Yeah I encounter this problem a lot as well. Ideally you would be using a component based framework that means you just write each component once and reuse it across your project like a Textarea component in react, but that doesn't work so well for HTML or PHP such as in WordPress themes.

    The way I usually go about working with these sort of projects is once I find one set of classes that I frequently reuse, I abstract them into there own class using @apply or just regular CSS in your main.css file that includes the Tailwind imports, for example I commonly create a class for screen reader only styling as well as buttons and inputs:

    main.css

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    
    @layer components {
      /* regular css because tailwind doesn't support clip & clip-path */
      .sr-only {
        clip: rect(0 0 0 0);
        clip-path: inset(100%);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
      }
    
      /* @apply tailwind classes to keep things consistent where possible */
      .textarea {
        @apply ml-8 mt-1 p-2.5 w-5/6 text-sm rounded-md !outline-none focus:shadow-sm focus:ring-1 focus:ring-pink-400;
      }
    }
    

    index.html

    <textarea class="textarea"></textarea>
    

    One thing I tend to do is force myself to only abstract these classes once I notice something becoming annoying to type or change constantly, so if it's just a simple section with some cards I usually wouldn't bother, but if it's a component you use on every page across the website then I turn it into an abstracted class. The reason I do this and my understanding of the Tailwind recommended way is to avoid falling back into the problem of naming things and having loads of classes that make changing styling more difficult as the project gets larger, at which point you may as well use regular CSS/SCSS. In my mind Tailwind puts flexibility before reusability, which does take some getting used to.

    On this docs-page talks about the ideal option depending on what you have available. I personally think Tailwind really shines when using it with something like React or Vue, but it definitely still brings value and flexibility to most other projects as well.