Fixing Class Composition in Tailwind CSS

This page summarizes the projects mentioned and recommended in the original post on dev.to

SurveyJS - JavaScript Form Builder with No-Code UI & Built-In JSON Schema Editor
Keep full control over the data you collect and tailor the form builder’s entire look and feel to your users’ needs. SurveyJS works with React, Angular, Vue 3, and is compatible with any backend or auth system. Learn more.
surveyjs.io
featured
Stream - Scalable APIs for Chat, Feeds, Moderation, & Video.
Stream helps developers build engaging apps that scale to millions with performant and flexible Chat, Feeds, Moderation, and Video APIs and SDKs powered by a global edge network and enterprise-grade infrastructure.
getstream.io
featured
  1. Tailwind CSS

    A utility-first CSS framework for rapid UI development.

    There are many opinions on how to deal with such cases. Some recommend using the @apply directive for your components’ base styles. Others argue that you should already consider all the possible variants of your component and use JavaScript logic to apply proper classes based e.g. on the component’s props.

  2. SurveyJS

    JavaScript Form Builder with No-Code UI & Built-In JSON Schema Editor. Keep full control over the data you collect and tailor the form builder’s entire look and feel to your users’ needs. SurveyJS works with React, Angular, Vue 3, and is compatible with any backend or auth system. Learn more.

    SurveyJS logo
  3. twin.macro

    🦹‍♂️ Twin blends the magic of Tailwind with the flexibility of css-in-js (emotion, styled-components, solid-styled-components, stitches and goober) at build time.

    One of the more promising alternatives is twin.macro - a Babel macro that processes Tailwind classes to generate JS objects understandable by various CSS-in-JS libraries. The developer experience (DX) of using it is amazing as you not only get all of Tailwind’s features without much change to your code, but you also get much more flexibility - all that on top of the traditional benefits of CSS-in-JS. Here’s an example code:

  4. vite

    Next generation frontend tooling. It's fast!

    While not too long, css`@apply is a lot to repeat for every class you want to “compile”. That’s why using Vite and some Rollup plugins (Vite uses Rollup under the hood) I was able to shorten it into this:

  5. babel-plugin-macros

    🎣 Allows you to build simple compile-time libraries

    One of the more promising alternatives is twin.macro - a Babel macro that processes Tailwind classes to generate JS objects understandable by various CSS-in-JS libraries. The developer experience (DX) of using it is amazing as you not only get all of Tailwind’s features without much change to your code, but you also get much more flexibility - all that on top of the traditional benefits of CSS-in-JS. Here’s an example code:

  6. vanilla-extract

    Zero-runtime Stylesheets-in-TypeScript

    Vanilla-extract allows you to utilize TypeScript as your CSS preprocessor, just like Sass. On top of that, it comes with Sprinkles - an atomic CSS framework that allows you to reproduce Tailwind’s utility classes.

  7. unocss

    The instant on-demand atomic CSS engine.

    Now, I’d like to mention one more Tailwind alternative that might be worth your attention - especially in regards to class composition - UnoCSS.

  8. Rollup

    Next-generation ES module bundler

    While not too long, css`@apply is a lot to repeat for every class you want to “compile”. That’s why using Vite and some Rollup plugins (Vite uses Rollup under the hood) I was able to shorten it into this:

  9. Stream

    Stream - Scalable APIs for Chat, Feeds, Moderation, & Video. Stream helps developers build engaging apps that scale to millions with performant and flexible Chat, Feeds, Moderation, and Video APIs and SDKs powered by a global edge network and enterprise-grade infrastructure.

    Stream logo
  10. linaria

    Zero-runtime CSS in JS library

    After exploring all the above alternatives (and more), I’ve decided to implement my own, custom solution. For that, I’ve turned to Linaria - a true zero-runtime CSS-in-JS library.

  11. astro

    The web framework for content-driven websites. ⭐️ Star to support our work!

    The above config is what I used to get the shorthand and Liniaria working in Vite. To give you an overview of how it works - the twis first replaced with css\@apply and then the css template literal tag is auto-imported where necessary. I’ve only used this setup with Vite and Astro (Vite-based) so I don’t know how hard it’d be to get it working in other bundlers (though pure Rollup should work as well).

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts

  • Tailwind vs Linaria: Performance Investigation

    4 projects | dev.to | 24 Apr 2025
  • CSS Style Guide for Web Dev?

    5 projects | /r/learnprogramming | 30 Jan 2023
  • The Anatomy Of My Ideal React Component

    4 projects | dev.to | 11 Mar 2022
  • Forget about styled components. Tailwind CSS is all you need.

    3 projects | dev.to | 25 Feb 2022
  • I created a blogging platform

    4 projects | /r/webdev | 7 Aug 2021

Did you know that TypeScript is
the 1st most popular programming language
based on number of references?