Oops! There was an issue with the sign in. Please try again.
You have successfully signed up. You can sign in now.
Oops! There was an issue with the sign up. Please try again.
You have successfully subscribed. Please check your email to confirm.
Oops! There was an issue subscribing. Please try again.
You have successfully signed up. You can sign in now.
How I like to use Tailwind

How I like to use Tailwind

The first time I visited Tailwind’s website I was really fascinated by its clean design and numerous code samples, ready to be used. My main interest in Tailwind wasn’t its value proposition to replace CSS, but the ability to build really quick prototypes for SaaS ideas.

I quickly setup a React project with Tailwind, which was fairly easy but I was immediately off put by the large amount of class names that now all my components needed to have. Most the business logic was now harder to read because of Tailwind, and its structure harder to follow.

This all changed when I discovered Tailwind Styled Components. If you are used to Styled Components or Emotion, the logic is very similar: You create an element, (outside of the render method), give it their styles and only afterwards you call it. The difference with this package is that instead of providing CSS, you give each element a list of Tailwind class names to apply the styling. All of this with the advantage of being able to also use variables to conditionally apply styles.

Before

<div className=`flex ${primary ? "bg-indigo-600" : "bg-indigo-300"} inline-flex items-center border border-transparent text-xs font-medium rounded shadow-sm text-white hover:bg-indigo-700 focus:outline-none`>
Tailwind without TW Styled Components

After

const Button = tw.div`
    ${(p) => (p.$primary ? "bg-indigo-600" : "bg-indigo-300")}

    flex
    inline-flex
    items-center
    border
    border-transparent
    text-xs
    font-medium
    rounded
    shadow-sm
    text-white

    hover:bg-indigo-700
    focus:outline-none
`
Using Tailwind Styled Components
<Button $primary={false}>
Using Tailwind Styled Components

I usually only use Tailwind to make quick prototypes, so I use it conjunction with Tailwind UI, which has a large amount of components readily available to be used.

My process when converting these samples to my project involves:

  • Creating the new component folder and respective index.ts
  • Creating a file named after the component which has it’s RxJS structure without any classnames (I like this because it eases searches and code identification in VSCode)
  • Creating a styles.ts file which includes Tailwind Styled Components and creates and exports all necessary elements to build the sample component.

Coming up with names for the elements is a bit hard, but the rule I use with Styled Components usually helps me here as well. If it’s a div to apply some spacing / alignment styles around an object, I usually call it SomethingContainer (e.g. MenuContainer). If it’s more specific or about styling I call it SomethingStyled (e.g. StyledMenuItem).

Below you can see the example of an header created with this structure:

export { default } from "./Header";
header/index.tsx
import { useOktaAuth } from "@okta/okta-react";
import { Link, useHistory } from "react-router-dom";

import Button from "../Button";
import {
  ButtonsContainer,
  LogoContainer,
  StyledHeader,
  StyledLogo,
} from "./styles";

const Header = () => {
  const { authState, oktaAuth } = useOktaAuth();
  const history = useHistory();

  return (
    <StyledHeader>
      <LogoContainer>
        <Link to="/">
          <StyledLogo src={`${process.env.PUBLIC_URL}/icon.svg`} />
        </Link>
      </LogoContainer>

      <ButtonsContainer>
        {authState.isAuthenticated ? (
          <Button light onClick={() => oktaAuth.signOut()}>
            Sign Out
          </Button>
        ) : (
          <Button light onClick={() => history.push("/signin")}>
            Sign In
          </Button>
        )}
        <Button to="/signup">Sign Up</Button>
      </ButtonsContainer>
    </StyledHeader>
  );
};

export default Header;
header/Header.tsx
import tw from "tailwind-styled-components";

export const StyledHeader = tw.header`
    flex
    justify-between
    items-center
    max-w-7xl
    mx-auto
    px-4 py-6
    sm:px-6
    md:justify-start
    md:space-x-10
    lg:px-8
`;

export const LogoContainer = tw.header`
    flex
    justify-start
    lg:w-0
    lg:flex-1
`;

export const StyledLogo = tw.img`
    h-8
    w-auto
    sm:h-10
`;

export const ButtonsContainer = tw.div`
    flex
    items-center
    justify-end
    md:flex-1
    lg:w-0
    gap-x-8
`;
header/styles.ts

Another useful thing that you can do with Tailwind Styled Components is creating Typescript interfaces when they receive props to apply different styles. Take as an example this Link component which receives two arguments:

import { Link } from "react-router-dom";
import tw from "tailwind-styled-components";

interface LinkProps {
  $light: boolean;
  $full: boolean;
}

export const StyledLink = tw(Link)<LinkProps>`
    whitespace-nowrap
    text-base
    font-medium
    disabled:opacity-50
    ${(p) =>
        p.$light
            ? "text-gray-500 hover:text-gray-900"
                : `
                    items-center
                    justify-center
                    px-4
                    py-2
                    rounded-md
                    text-white
                    bg-gradient-to-r
                    hover:from-purple-600
                    hover:to-green-300
                    from-yellow-500
                    to-pink-500
    `}
	${(p) => (p.$full ? "flex w-full" : "inline-flex")}
`;

Hope you enjoyed the article and have fun with Tailwind!