DEV Community

Eric SK.C for Giant Machines

Posted on

Set Sail with Tailwind CSS

TailwindCSS

CSS frameworks have become incredibly prevalent in web design over the years, with Google’s Material Design aesthetic gradually appearing throughout the web and Bootstrap’s library of plugins and themes becoming a popular default.

Good news is, the days of pages looking like this...

Old Amazon
are long behind us, thanks in part to CSS frameworks.

But like many rebellious people, you may be asking, what can I use that’s not mainstream yet? Is there a better, more modern solution? Isn’t there something out there that doesn’t involve Google’s or Twitter's participation at all?

Tailwind CSS, a new up-and-comer, is a framework that’s been making a name for itself since 2017. Tailwind was rated highest in satisfaction and interest by users from over 100 countries in both 2019 and 2020, as recorded by the State of CSS survey.

State of CSS Survey

Tailwind provides a collection of pre-built utility classes, allowing developers to directly style HTML elements without needing to create CSS classes or write any CSS at all.

This lets Tailwind shine in its simplicity, flexibility, and available customization options. Unlike Material and Bootstrap, which provide opinionated pre-built elements (and which require a substantial setup and demanding syntax), Tailwind provides hassle-free access to styling CSS simply and quickly via utility classes.

If you’ve ever had a great idea for a frontend project, jumped straight into coding, and wanted to immediately flesh out that brilliant UI in your mind, Tailwind would allow you to style quickly before the inspiration left you, simply by slapping some of their utility classes on your markup.

In this article, we’ll be discussing how Tailwind works and the benefits and drawbacks of using it. We'll examine the basic setup and workflow of Tailwind. Then we'll look at implementing Tailwind with SASS or Styled Components, as well as building for responsiveness.

Let’s get on with it, shall we?

How does Tailwind work?

Utility Classes

Tailwind is a utility-first CSS framework. A utility class is a reusable CSS class that styles an element for a specific purpose.

Let’s say we’re expecting multiple elements to need a background color of blue. To create a utility class for this, we’d create a CSS class named bg-blue and give it the style background-color: blue. Now we can place our utility class bg-blue onto the numerous HTML elements where the background needs to be blue.

With that concept understood, Tailwind essentially provides a huge collection of pre-built utility classes so you don’t have to create them yourself. It relies on stacking these classes onto HTML elements to fully style the element.

Using Tailwind, you may never need to write CSS. Instead, you'd just insert utility classes. For example, to easily create a button with rounded corners, a mild box shadow, and centered white text, you’d simply add the following utility classes to your element:

<button className="bg-blue-300 rounded-md shadow-md text-center 
p-8 text-white">
  Button
</button>

* NOTE: The examples in this blog will be referencing React
 components, hence the usage of "className".
Enter fullscreen mode Exit fullscreen mode

That's all you'd need to do to get a styled button that looks like this:

Blue Button using Tailwind styles

Tailwind provides hundreds if not thousands of utility classes, each with specific styling purposes. There is a class named .text-center with a single CSS property of text-align: center, another named .p-8 that has padding: 2rem, and so on. This is how Tailwind works.

Benefits & Drawbacks

Pros

  • The most apparent benefit to using Tailwind’s utility classes is it allows the developer to create their markup and style it at the same time without the need of creating CSS classes (or writing any CSS!). A developer using Tailwind would never need to leave their HTML or JSX code when building out views and components.

    • This can be especially beneficial if you’ve ever needed to put together a quick demo or MVP, or simply scaffold a UI to better visualize your project.
  • An enormous perk provided by default is that Tailwind will automatically remove all unused CSS from the bundle sent to the browser. At build time, Tailwind will purge all unused CSS classes, creating the smallest CSS bundle your code can possibly provide, averaging at less than 10kb. This can dramatically improve page load times.
  • As a styling framework, Tailwind is arguably less opinionated than other frameworks like Bootstrap and Material. Very often when using other frameworks, developers will find themselves rewriting the CSS provided by the framework to fully suit their needs.

Cons

  • The initial learning curve of Tailwind can be unappealing, as you will inevitably find yourself returning to its docs to learn the correct utility class name. Something as traditional as setting padding-top: 1rem is nowpt-4 with Tailwind. In the beginning, this could potentially outweigh all the benefits Tailwind provides in regards to speed.

    • Once you’ve familiarized yourself with Tailwind, however, I guarantee you’ll find the utility class names to be as simple as remembering CSS attributes themselves.

Tailwind padding class names

  • Though Tailwind is relatively unopinionated, the pre-built utility classes still have set values. For example, text-red-300 is a utility class for text color with preset values for red, specifically rgba(252, 165, 165, 1). Thankfully, these defaults can all be adjusted in a tailwind.config.js file to suit your needs.
  • By default, Tailwind doesn’t provide any styled components out of the box. All the components provided in a library like Bootstrap (for example, general navigation, buttons, headers) need to be implemented from scratch.

Tailwind Implementation & Workflow

To start off, you’ll want to install Tailwind with npm. To get the latest version and its peer dependencies, run npm install -D tailwindcss@latest postcss@latest autoprefixer@latest.

If you’re going to customize some things, run npx tailwindcss init to create the tailwind.config.js file. This file allows custom implementation of styling, which we’ll discuss in the next section.

To inject Tailwind’s functionality, you will need a CSS file that includes these lines:

/* ./your-css-folder/styles.css */

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

From here, you’re free to jump straight into coding.

Some things to keep in mind are the purpose and roadmap of your project. If you simply need something up and running with a deadline coming up, the basic implementation of Tailwind is fine.

If you know you’re going to be refactoring and potentially even removing Tailwind further down the road, be sure to pair your Tailwind code with SASS or Styled Component files.

Keeping these details in mind will foster a cleaner codebase, or a better transition into one.

Tailwind Config

Chances are you’re going to be customizing your Tailwind utility classes, because let’s be honest, their utility library doesn’t include everything. As an example, any kind of custom animation that isn’t a pulse or bounce will require a configuration.

To set this up, make sure to run npx tailwindcss init. This will create a minimal tailwind.config.js file in the root of the project.

Here, you can set whatever you might need that isn’t included by default in Tailwind, which may be custom fonts, animations, specific breakpoints, new utility classes, or adjusting Tailwind’s pre-built utility classes. Any custom styles here will take precedence over Tailwind’s existing classes.

module.exports = {
  purge: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {
      fontFamily: {
        sans: [
          "AvenirLTPro-Heavy",
          "AvenirLTPro-Light",
          "AvenirLTPro-Black",
        ],
        body: ["AvenirLTPro-Medium"],
        light: ["AvenirLTPro-Light"],
      },
      screens: {
        xs: "320px",
        sx: "420px",
      },
      colors: {
        blue: {
          lighter: "#3064b1",
          light: "#CAE0FE",
          DEFAULT: "#0E71FB",
          dark: "#082959",
        },
        gray: {
          lightest: "#F7FAFC",
          lighter: "#EBEFF5",
          light: "#E6EAF0",
          DEFAULT: "#D7DBE0",
          dark: "#6E6E6E",
          darkest: "#333333",
        },
      },
      animation: {
        slideIn: "slideIn 200ms ease-in-out 1",
      },
      keyframes: {
        slideIn: {
          "0%": { transform: "translateX(-100vw)" },
          "100%": { transform: "translateX(0)" },
        },
      },

Enter fullscreen mode Exit fullscreen mode

Tailwind with Other Styling Packages

An obvious issue with Tailwind is the verbose class names that will eventually clutter your HTML or JSX. If we look at the previous example for the button, the full list of classes applied is bg-blue-300 rounded-md shadow-md text-center. If we wanted to add more styling, we would need even more utility classes, making this line even longer.

And if every element were to look like this, the markup would become harder and harder to read.

const Name = () => {
  return (
    <div className="flex flex-col md:flex-row overflow-ellipsis
overflow-hidden">
      <div className="p-1 w-11r md:w-20r md:p-2 lg:w-29r 
inline-block text-gray-darkest font-sans flex items-center">
        <h3 className="text-xs overflow-ellipsis overflow-hidden
xs:truncate md:text-base md:overflow-clip
md:whitespace-normal md:overflow-visible max-h-10">
          {name}
        </h3>
      </div>
      <div className="p-1 w-5r md:w-8r inline-block flex 
items-center justify-center">
        <p className="text-xs md:text-base">
          {date ? formatDate(date) : "Unspecified"}
        </p>
      </div>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Possible solutions to this problem involve pairing Tailwind with either SASS or Styled Components.

With SASS Using @apply

A common practice with Tailwind is to combine its usage with SASS/SCSS. A convention I've found useful is to limit the utility classes on any HTML element to 5 or 6. If an element requires further styling, you can use @apply to style a SASS class using Tailwind utility classes, like so:

.card-body {
  p {
    @apply px-4 pb-4 text-lg pt-0 font-helvetica-neue text-center
text-white
  }
}
Enter fullscreen mode Exit fullscreen mode

Then, you’re free to set this class wherever you need.

With Styled Components Using tw.macro

To use Tailwind alongside Styled Components, we’re going to need some extra dependencies, these being tailwind.macro and babel-plugin-macros. The combination of these two will allow Babel to read Tailwind utilities.

Once that’s done, you can start setting Tailwind utilities under className in your styled components.

import styled from "styled-components";
import tw from "tailwind.macro";

const AppStyles = styled.div.attrs({
  className: "w-full h-screen flex flex-col 
items-center justify-center"
})`
  h1 {
    ${tw`font-sans text-6xl text-teal-500`}
  }
  p {
    ${tw`text-lg text-gray-700`}
  }
  ul {
    ${tw`inline-flex mx-5`}
  }
`;
Enter fullscreen mode Exit fullscreen mode

For a more detailed implementation, check out these blogs by Ibrahima Ndaw and Derek Shanks.

Building for Responsiveness

Media Queries

One of the nice perks of using Tailwind is the simplicity of responsive styling. By default, Tailwind is mobile-first in regards to responsiveness. In other words, the breakpoints under the hood are specified using min-width.

<button className="bg-blue-300 rounded-md shadow-md text-center
p-8 text-white text-sm md:text-md md:p-10 lg:text-lg">
  Button
</button>
Enter fullscreen mode Exit fullscreen mode

In this example, the font-size and padding will change when the breakpoint for md is reached, and the font-size is enlarged even further when lg the breakpoint is reached. To know the exact measurements for sizes like md or lg, you’ll have to refer to the Tailwind docs for the specific attributes. In regards to breakpoints, sm is 640px, md is 768px, and lg is 1024px. These can all be adjusted, and more sizes can be added, in the tailwind.config.js file. For example, if you wanted md to represent 800px, you can change that in tailwind.config.js.

// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      'sm': '640px',
      // => @media (min-width: 640px) {...}

      'md': '800px',
      // => @media (min-width: 800px) {...}

      'lg': '1024px',
      // => @media (min-width: 1024px) {...}

      'xl': '1280px',
      // => @media (min-width: 1280px) {...}

      '2xl': '1536px',
      // => @media (min-width: 1536px) {...}
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Conclusion

What Tailwind provides is a streamlined experience to web styling. It doesn’t require a massive amount of boilerplate to get started and certainly doesn’t push pre-styled button components or form elements which you might end up needing to restyle yourself.

Tailwind simply provides developers an efficient and fast method of styling so they can get straight to work. It can especially come in handy when you want to quickly add some pizzazz to early stage and personal projects, and it can even scale to larger projects as well.

Cheers
You made it to the end! Thanks for reading!

Discussion (0)