DEV Community

Cover image for Utility-first CSS - You have to try it first!
Michael Z
Michael Z

Posted on • Updated on • Originally published at michaelzanggl.com

Utility-first CSS - You have to try it first!

Originally posted at michaelzanggl.com. Subscribe to my newsletter to never miss out on new content.

Years ago, Bootstrap has already provided us with a set of utility classes. For example text-center for text-align: center;. Over the years, such frameworks started shipping more and more just like this.

Probably my favorite ones are spacing utilities. mt-1 for margin-top: 2px;, px-3 for padding-left: 8px; padding-right: 8px;, m-auto for margin: auto etc. Gone are the days where I have to invent a class name for something abstract, just so I can give it some padding.

So recently, version 1.0 of Tailwind CSS was released. Its approach is vastly different from traditional CSS frameworks. Rather than providing high level styles and components, it keeps everything low level, focusing only on utility classes.

<div class="md:flex bg-white hover:bg-gray-200 rounded-lg p-6">
    <img class="h-16 w-16 md:h-24 md:w-24 rounded-full mx-auto md:mx-0 md:mr-6" src="avatar.jpg">
    <div class="text-center md:text-left">
      <h2 class="text-lg">Erin Lindford</h2>
      <div class="text-purple-500">Customer Support</div>
      <div class="text-gray-600">erinlindford@example.com</div>
      <div class="text-gray-600">(555) 765-4321</div>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

This looks horrendous! My HTML will be forever ruined!!

This is probably most people's first reaction when they see this. Hey, this is breaking various best practices on semantics after all.

It just feels wrong... Until you try it for yourself!

I repeat, you have to try it out to understand it!

Open up codepen and try recreating something from here.

At least for me, it feels weirdly natural and productive. No longer having to switch between HTML and CSS is a bliss. If you think about it, when was the last time you edited HTML without changing its styles at the same time?

So let's tackle the most common question!

Why not just write inline styles?

  • With inline styles you are very limited. No media queries or pseudo classes.

  • With tailwind CSS you pick from a set of classes, so rather than thinking up a new font size, color, margin, padding, etc. evertime you add styles, you just pick something from the existing set. As Adam Wathan puts it Designing with constraints. This has two major benefits.

  1. You will save a lot of time not having to come up with new sizes and colors all the time

  2. Reusing the same sizes, etc. will naturally also improve the UI a lot.

Let's go through some more benefits

  • No more wasting time inventing bad classnames like this-wrapper, that-body.

  • breakpoint prefixes! Let me say that again, breakpoint prefixes!! In other words, get rid of 99.999% of media queries. xs:p-3, md:text-center...

  • Customizable to the core. Don't like a certain property? Override the default in the configurations! You can even add your own utility classes while still making use of breakpoints, pseudo classes etc.

  • JS Framework agnostic. Works out of the box with vue, react, angular, blade, traditional sites etc. That means you don't have to learn a new CSS framework just because you decide to use a different JS framework.

  • Find yourself repeating a set of classes? No problem, it's called "utility-first", not "utility-only". TailwindCSS even helps you making new classes using existing utilities

.btn {
  @apply rounded-full text-sm text-white bg-blue-400 shadow-lg;
}
Enter fullscreen mode Exit fullscreen mode
  • You no longer need to maintain huge CSS/SCSS files. CSS grows very very fast after all.

  • This goes together with the previous benefit. With a utility-first approach, you will be much more confident making changes.

  • No framework lock-in that dictates how your buttons etc. should look and feel like. This will make your design unique.


If you still have doubts, watch the creator of TailwindCSS make a website from scratch.

TailwindCSS also ranked extremely high in The State of CSS 2019.

Conclusion

Did you know GitHub is following this approach as well?

Maybe I just really like it because it is feels so refreshing. Maybe I am overlooking the drawbacks and only focus on the benefits it provides. That is definitely possible. So let's see how I feel about this in a year from now. But for the time being, I am really enjoying it!

With all that being said, try it out for yourself and hopefully you will enjoy it as much as I do!


If this article helped you, I have a lot more tips on simplifying writing software here.

Top comments (14)

Collapse
 
danderson profile image
Dale Anderson

While I can appreciate the simplicity and directness of this approach, it misses a fundamental aspect of CSS and HTML that many people miss - it's about semantics, about creating a domain specific language that clearly expresses the intent of the styling and markup. For example, it might be appropriate in an application to style buttons two different ways - rather than implement two different buttons each with their own set of paddings, margins, etc., etc., we implement two CSS classes with a name that clearly expresses the intended use - primary, navigation, etc.

There is also a good point in Sean's tweet in the previous comments about building with utilities and refactoring emerging patterns - definitely sage advice, but I feel there is a parallel with TDD here. Do your UI/UX design first and then make your acceptance tests pass - a skilled designer will know the common design patterns and guidelines (e.g. Google's Material Design) and be able to incorporate them into a design language for the application, without needing to refactor them out later.

All works in theory, anyway :)

Collapse
 
michi profile image
Michael Z

You can still create vue/react/... components for each thing you want to represent. That way, modifiers (size, color etc.) simply become props.

Collapse
 
danderson profile image
Dale Anderson

Yeh, true, components do give you another way of encapsulating styling - the whole "CSS in JS" thing. There isn't a right or a wrong way, or even better or worse, just pros and cons. I'm one of these strange people who actually kinda likes CSS despite its quirks and thinks it's fit for purpose, so I'll always advocate using it semantically, but each to their own! Good food for thought anyway.

Collapse
 
joserochadocarmo profile image
José Rocha

@apply?

Collapse
 
perpetual_education profile image
perpetual . education • Edited

This looks horrendous! My HTML will be forever ruined!!

That's what we still think

codepen.io/sheriffderek/pen/QWwyJmB

Why? When you could write this?

<user-card class='modifier?'>
  <picture class='avatar'>
    <img src='{{user.image}}'>
  </picture>

  <h1 class='name'>@{{user.handle}}</h1>
  <h2 class='title'>{{user.title}}</h2>

  <footer class='actions'>
    <a class='link' href='{{user.url}}'>
      {{user.cta}}
    </a>
  </footer>
</user-card>
Collapse
 
michi profile image
Michael Z

I go more into detail regarding the benefits in this interactive tutorial: learning-by-vueing.netlify.app/tai...
Mind giving it a go?

Collapse
 
perpetual_education profile image
perpetual . education

We'll check it out = but this type of URL https://learning-by-vueing.netlify.app/tailwind/pre/ is quickly becoming it's own meme. learning + vueing + netlify + app + tailwind + and even pre ! haha.

Collapse
 
perpetual_education profile image
perpetual . education • Edited

Your playground area is cool. And the way you explain it is nice. Great job.

However, maybe we're crazy... but we LIKE CSS. So, we're not in any hurry to abstract it away. We've also built out really complex them-able systems (think old myspace) - and we're not seeing any pros of having super horrendous markup. Especially when you add in all of the dynamic properties and stuff...

<li x-for="someArray as currentItem" @event="doSomething" class="xd=15 color-blue-1299 roundy-thingies small-but-big-on-small-medium-exept-when-not shadow-small-lighter float-left-only-on-large etc etc-2">{{currentItem.content}}</li>

vs.

{{#forEach users as |user|}}
  <UserCard @model='user' />
{{/forEach}}

.

<user-card>
  <h2 class='name'>{{model.name}}</h2>
  <h3 class='title'>{{model.title}}</h3>
</user-card>

.

user-card
  round-corners()
  drop-shadow()
  padding: $pad
  .name
    attention-voice()
  .title
    calm-voice()
    margin-top: $pad

Or something readable. (not sure if this is valid / but for example)

Tailwind is GREAT if you are trying to avoid being a front-end developer / but we enjoy writing code for the front-end.

Collapse
 
perpetual_education profile image
perpetual . education

What if you wanted to switch CSS later?

Collapse
 
fasani profile image
Michael Fasani • Edited

I tried tailwind for the first time today. Originally I saw the code and was just like what a complete mess... I hate it. 20 minutes later... I really like it. Actually I have always felt like CSS does not scale well on large projects, it grows and grows and grows and then there is dead CSS everywhere.... and it's nested and kind of awkward. It does bloat the HTML but this could be minimized in the same way Facebook showed with their stylex library. I will need to create multiple themes and colour schemes so maybe I am biast because I think for that it will work really well.

Collapse
 
michi profile image
Michael Z

That's great to hear! If you feel a little skeptical I also created a free interactive tutorial on Tailwind here which covers even more benefits than this blog post.

Collapse
 
seangwright profile image
Sean G. Wright • Edited

Glad to see a nice overview of utility CSS. Thanks for writing this!

I've been trying to describe the benefits, as I see them, too.

Liquid error: internal
(twitter.com/seangwright/status/113...)

and

Liquid error: internal
(twitter.com/seangwright/status/113...)

"Content-layer semantics are already served by HTML elements

"Class names impart little or no useful semantic information to machines

"The primary purpose of a class name is to be a hook for CSS and JavaScript

"Class names should communicate useful information to developers

There are so many cool things we can learn by turning out preconceptions about CSS on their heads. 🙃

Collapse
 
milosdukic profile image
Milos

Great article. I have switched to TWCSS from Bootstrap and it is really easy to work with once you get your mind around it. Especially responsive design. Cheers!

Collapse
 
milosdukic profile image
Milos

Hi I have written an article on how to integrate TailwindCSS with Angular8 - dev.to/laptoptheone/tailwindcss-an...