DEV Community

Cover image for Tailwind CSS under the hood

Tailwind CSS under the hood

Max Shen on February 10, 2024

Tailwind CSS defines itself on its official site as: A utility-first CSS framework packed with classes. In this post I'll explain to you what d...
Collapse
 
karsten_biedermann profile image
Karsten Biedermann

Thank you for your excellent article 👍. I stopped using it at some point due to the poor code readability. In reality, in large projects, it often looks like this:

<a class="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"></a>

There's a good reason why solutions like this now exist, offering readable classes for use: daisyui.com

Collapse
 
seandinan profile image
Sean Dinan • Edited

I agree that it becomes a bit cluttered looking as a big long string, but I stopped inlining classnames in JSX a while back and it pretty much resolved the problem. My usual component structure is something like:

- /ControlsBar
  - index.jsx
  - utils.js
  - ControlsBar.stories.js
Enter fullscreen mode Exit fullscreen mode

so that the component file is something like:

import { classes } from './utils';

export default function ControlsBar({onSave, onCancel}){
  return (
   <div className={classes.wrapper}>
    <button className={classes.cancel} onClick={onCancel}>Cancel</button>
    <button className={classes.save} onClick={onSave}>Save</button>
  </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

and the utils file has:

export const classes = {
  wrapper: 'flex justify-between items-center border-t border-grey-3',
  cancel: 'text-grey-4 bg-grey-1 hover:bg-grey-2',
  save: 'text-blue-4 bg-blue-1 hover:bg-blue-2',
}

/* ...any utility functions for the particular component */
Enter fullscreen mode Exit fullscreen mode
Collapse
 
brense profile image
Rense Bakker

This is exactly what PandaCSS already does.

Thread Thread
 
seandinan profile image
Sean Dinan • Edited

I think it's a pretty common pattern. I made a package (tailwind-classlist) back in 2018ish that did something similar, although it's no longer maintained. Handled merging conflicting classes and everything as well.

Thread Thread
 
brense profile image
Rense Bakker

Nice!

Collapse
 
faiq157 profile image
Faiq Ahmad

NYC bro

Collapse
 
adaptive-shield-matrix profile image
Adaptive Shield Matrix • Edited

If you do not like how all classes are smashed together maybe spend some time grouping them together ?

Here is an example from one of the more complex styled component taken from shadcn Dialog:

  className={classMerge(
     "z-50 relative", // overlay
     "w-full", // layout
     "grid gap-4", // layout children
     "bg-background", // bg
     "p-6 shadow-lg sm:rounded-lg", // border
     "duration-200", // animation
      "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", // animation open
      "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", // animation closed
     className,
   )}
Enter fullscreen mode Exit fullscreen mode

I find the code above pretty readable, easy to summarize and skim through.
Yes, its a little bit of extra work to write it like this.
Yes, you have to create separate components for each used div -> a good practice in React/Svelte/Solid/Vue anyway.

Collapse
 
littleoddboy profile image
Amirhosein Kalari!

I find something intresting. I'm not sure about the date, but it was 2022 I think that TailwindCSS and Prettier (a VScode add-on) featured with a very good updates. While you're doing refactoring the structure of your code with this add-on, it will sort all of your classes. Check it out in the end of the first page of tailwindcss.com
Enjoy it!

Thread Thread
 
karsten_biedermann profile image
Karsten Biedermann

When I spend more time making something disorganized organized, it's often better to do it myself. I'm taking a more pragmatic approach: native CSS is now really good. To make something clear and maintainable, I don't need a framework, just a good method to do it.

Thread Thread
 
adaptive-shield-matrix profile image
Adaptive Shield Matrix

I know of it, I tried it.
I did not like the auto ordering of the tailwind classes.

If they are components that I use everywhere (like buttons) I want to make them as readable as possible.
The approach in my code example solved that goal in the best possible way known to me.

Collapse
 
bjoentrepreneur profile image
Bjoern

Like it a log. classMerge is amazing. Thanks for sharing :)

Collapse
 
bjoentrepreneur profile image
Bjoern

I like Tailwind because there are so many libs that build up on it, so you can use a solid set of components that were built with Tailwind, e.g. HeadlessUI or TailwindUI, so you can get the groundwork done fast and then customize them the way you want, while still keeping the option to fully change components with the ease of use of the Tailwind framework.

Collapse
 
brense profile image
Rense Bakker

Headless UI doesn't even have 1% of the components that other component libs offer and tailwind ui is a paid solution.

Thread Thread
 
bjoentrepreneur profile image
Bjoern

That's true, and I don't mind paying for components if they are well-made and maintained. TailwindUI is a great team with nice support and I can use their components to bring my projects up to speed in almost no time :)

Thread Thread
 
brense profile image
Rense Bakker

I'm not a fan of paying for things that should be open source.

Collapse
 
adaptive-shield-matrix profile image
Adaptive Shield Matrix

daysyui -> is horrible in accessability. Its okay to use it for purely ui/graphical/design stuff but not for interactive components.

The web is pretty much all about accessibility, so ignoring it defeats the purpose to do web development in the first place.

If you want to do accessibility right in React then one of the 2 libraries is the way to go

Svelte/Sollid/Vue have their own similar specialized component libraries

Collapse
 
karsten_biedermann profile image
Karsten Biedermann • Edited

I cannot assess the quality of DaisyUI in terms of accessibility, but my point was that Tailwind is very cluttered in the DOM for my taste. Perhaps it is also important to say from which perspective I decide whether Tailwind is suitable for me. I build less in the way of applications and more websites. For me, it was a nightmare to write pseudo-elements, states, and simple appearances in Tailwind. I find this comparison here by DaisyUI very apt 😂.

Image description

Image description

Thread Thread
 
adaptive-shield-matrix profile image
Adaptive Shield Matrix

I would disagree on the "websites are more complex than web app in terms of layout" claim

Proof
twitter.com/masumparvej_/status/17...

-> Try doing something like this to look good and responsive on all screen devices

Thread Thread
 
karsten_biedermann profile image
Karsten Biedermann

True!

Collapse
 
m4xshen profile image
Max Shen • Edited

I personally love NextUI. It works well with Tailwind and also has good accessibility (built on top of React Aria).

Collapse
 
pengeszikra profile image
Peter Vivo

I like to use tw fare better than using any other CSS solution because the layout related solution so simple like grid gap-2 for vertical list. Also can solve dark/light skin change and responsive design at zero cost.

Collapse
 
brense profile image
Rense Bakker

Tailwind likes to pretend it's the only option with those benefits, but that's not really (really not) true. PandaCSS for example has the same benefits, but none of the downsides of having to learn a new utility class language.