DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 963,673 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Tailwind with React
Ryan Lanciaux
Ryan Lanciaux

Posted on • Originally published at ryanlanciaux.com

Tailwind with React

Tailwind is a CSS library in a similar space to things like Bootstrap or Bulma. Tailwind is different that instead of providing CSS for full components, it provides low-level utility classes. What this means is that instead of using class=β€œbutton” or β€œcard” or something else, you’ll define your own button by composing Tailwind’s utility classes.

For an example of this, we’ll look at some HTML of a card created with Bootstrap and then a card created with Tailwind.

Bootstrap - See example on CodePen

<!-- from the Bootstrap documentation
     https://getbootstrap.com/docs/4.0/components/card/
-->
<div class="card" style="width: 18rem;">
  <img
    class="card-img-top"
    src="https://www.fillmurray.com/300/300"
    alt="Card image cap"
  />
  <div class="card-body">
    <h5 class="card-title">Card title</h5>
    <p class="card-text">
      Some quick example text to build on the card title and make up the bulk of
      the card's content.
    </p>
    <a href="#" class="btn btn-primary">Go somewhere</a>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Tailwind - See example on CodePen

<div class="w-64 rounded overflow-hidden shadow-lg">
  <img
    class="w-full"
    src="https://www.fillmurray.com/300/300"
    alt="Bill Murray Placeholder"
  />
  <div class="px-6 py-4">
    <div class="font-bold text-xl mb-2">Card Title</div>
    <p class="text-gray-700 text-base">
      Some quick example text
    </p>
  </div>
  <div class="px-6 py-4">
    <button class="bg-blue-800 py-2 px-2 rounded text-white">
      Go Somewhere
    </button>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

You may have noticed that the Tailwind card has more verbose CSS class properties. However, we can now adjust how our component looks without changing CSS directly.

For example, if we wanted to give the card a background, we could apply a bg-color class to our opening div: <div class="w-64 rounded overflow-hidden shadow-lg bg-indigo-300">...</div>. The bg-indigo-300 class is one example of a Tailwind Utility Class.

With React

We’re going to start with a default Create React Project.

> npx create-react-app react-tailwind-example
Enter fullscreen mode Exit fullscreen mode

Next, we'll add a couple dependencies

> yarn add tailwindcss tailwind.macro@next @emotion/core @emotion/styled
Enter fullscreen mode Exit fullscreen mode

If you prefer styled-components, you could include that instead of @emotion/core @emotion/styled

We’re ready to start writing some example code that uses these libraries. We'll replace App.js with the following code:

import React from "react";
import styled from "@emotion/styled";
import tw from "tailwind.macro";

const Button = styled.button`
  ${tw`bg-gray-300 text-yellow-900 px-8 m-8 rounded h-20 text-3xl`}
`;

export default function() {
  return <Button>Testing</Button>;
}
Enter fullscreen mode Exit fullscreen mode

Example output:

The styled component, Button, is using the Tailwind Macro tw to apply utility classes for things like a background color, rounded corners, font-size, etc. Combining Tailwind with Emotion or Styled-Components allows us to build flexible components quickly.

Using Tailwind CSS with my React applications has been extremely useful for me. I hope you find it helpful also.

Top comments (13)

Collapse
 
digioi profile image
Mike DiGioia • Edited on

You can simplify it a bit more with the following.

const Button = styled.button`
  ${tw`bg-gray-300 text-yellow-900 px-8 m-8 rounded h-20 text-3xl`}
`;
Enter fullscreen mode Exit fullscreen mode

to

const Button = tw.button`bg-gray-300 text-yellow-900 px-8 m-8 rounded h-20 text-3xl`;
Enter fullscreen mode Exit fullscreen mode

You do this by updating the babel macro config with something like

{
  tailwind: {
     config: tailwindConfig, // if you added a config file
     styled: '@emotion/styled',
  }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
stevenacoffman profile image
Steve Coffman

Hey Ryan,
Very nice! I'm not familiar with Tailwind.Macro or babel-plugin-tailwind-components. Would they provide the same cut-what-is-not-needed benefits as PostCSS + Purgecss, or would you consider using both?

Collapse
 
ryanlanciaux profile image
Ryan Lanciaux Author

That's a great question and I'm not entirely sure right now. I tried to find a bit more info on it but to no avail. I have a project where I'm using this and next time I'm in the code, I may try to do a production build and see if it's doing any of the purging type operations.

If it's not, it'd likely be good to do that still :D

Collapse
 
ryanlanciaux profile image
Ryan Lanciaux Author

Very nice! Thanks

Collapse
 
dbshanks profile image
Derek Shanks

Ryan! Thank you very much for your demonstration. You managed to sell Tailwind far better than anyone else has.

I’m a CSS specialist, my primary focus is designing efficient style workflows. I love styled-components.

I’ve been wanting to bring Tailwind on for awhile because there are several huge benefits as the UI styling is predictable and very nice to work with.

I absolutely cringed at the utility classes overtaking the template. React can get busy all on its own without Tailwinds class pollution.

The styled-component method is a game changer and now I have a new style workflow to integrate. Exciting!!! πŸ™ŒπŸ™Œ

Collapse
 
ryanlanciaux profile image
Ryan Lanciaux Author

Thanks a ton for checking it out - so glad it was helpful! :D

I had a very similar reaction when looking at Tailwind initially. "This looks nice but I fear what it'll turn my components into" πŸ˜€

Collapse
 
alex_barashkov profile image
Alex Barashkov • Edited on

Thank you for the article Ryan. I still can't understand tailwind approach that looks very similar to me with writing styles inline. So there are no difference between writing for example div class="overflow-hidden" and style="overflow:hidden".

Collapse
 
ryanlanciaux profile image
Ryan Lanciaux Author

Thank you. This is totally understandable that it looks similar to inline styling on occasion. I prefer the Tailwind approach using "micro CSS classes" opposed to inline styling. It shines when you have more properties you're applying especially on more than one page. If we wanted to apply a background, rounded corners, font-size, etc. it would be more likeclass="bg-indigo-300 rounded text-sm" (etc.).

Since these are classes and not inline, if we ever needed to update what font was used, anything using the Utility class would be styled the same. Tailwind's theme docs for a little more on this.

Collapse
 
liweiyi88 profile image
Julian Li • Edited on

I would say the main benefit of tailwind is that it provides you with a consistent design system which scales well. you don't need to think about what is degree of green I need to use as background and what is degree of green I need to use as the text color. simply use the pre-defined class like text-green-100 or text-green-500 without thinking about the hex color. It also works the same way for scaling the font size, without thinking about what specific font size used for heading or paragraph. Simply try text-lg, text-base to see how it fits your design.

Collapse
 
lem01 profile image
Laurent Lemaire • Edited on

Thanks for this good article!

How would you create the tailwind string parameter programmatically?
If let's say I want to add tailwind classes dynamically how would this work?

I tried adding my tailwind classes to a string and the pass it to the macro as a parameter but it doesn't seem to work.

  let twStr = ``
  twStr += (padding) ? 'pt-16 pb-16' : ''
  twStr += (altBackground) ? 'bg-gray-100' : ''

  const SSection = styled.section`
    ${tw`
      ${twStr}
    `}
    width: 2000px
  `
  return <SSection>{children}</SSection>

This works if rather than using the$(twStr) I use "pt-16 pb-16" (as a string a not as a variable).

Any hint?

Collapse
 
rodrigosaling profile image
Rodrigo Saling

Hello Ryan! Thanks for the tutorial!

I was using Tailwind with the PostCSS + Autoprefixer method and I thought that changing to styled-components would be an easy solution for when you want to disable a button or an input field.

But the main thing is that the Base style, they call it "Preflight", doesn't work anymore. Before I had this huge CSS file that was imported to my App, and the margins, paddings, and fonts were all working fine.

Now I have no clue on how to load these base styles. Do you have any idea on how to to that?

Thanks!

Collapse
 
astrit profile image
Astrit

Nice work Ryan πŸ‘

Collapse
 
ryanlanciaux profile image
Ryan Lanciaux Author

Thank you :D

This post blew up on DEV in 2020:

js visualized

πŸš€βš™οΈ JavaScript Visualized: the JavaScript Engine

As JavaScript devs, we usually don't have to deal with compilers ourselves. However, it's definitely good to know the basics of the JavaScript engine and see how it handles our human-friendly JS code, and turns it into something machines understand! πŸ₯³

Happy coding!