Tailwind CSS Crash Course styling the app - vonschappler/Ultimate-React GitHub Wiki

What is Tailwind CSS?

As said on their website, Tailwind CSS is a utility-first CSS framework with utility classes like flex, text-center, rote-90 and many others that can be composed to build any design, directly on your markup (HTML or JSX).

The utility-first, also known as (atomic css) approach consists in writing small classes with a single purpose and make use of combinations of those classes to build entire layouts. Most of those classes are already defined in Tailwind CSS, meaning that no new CSS is necessary to be written. Instead, we make use of some of those pre-build tailwind classes.

Pros and cons of Tailwind CSS:

Pros: Cons:
There is no need to think about naming classes Markup (HTML or JSX) looks unreadable, with lots of class names
There is no need to jump between files to write markup styles There is need to learn a lot of classes names used frequently
This allows immediate understanding of the styling in any project that uses Tailwind It's necessary to install and setup tailwind for each project
It's a desing system with many decisions taken for you, making the UI look better and consistent It feels like we are giving up on "vanilla CSS"
Saves a lot of time while writing CSS styles Many people hate Tailwind for no reason, even before trying it out

It's important to notice that Tailwind's documentation and integration with VisualStudio Code (via the official Tailwind extension) are REALY GREAT!


Setting up Tailwind CSS:

In order to install and setup Tailwind with Vite, refer to the documentation available on Tailwind website.

If a different framework is being used, the documentation can be used for settin up and installing Tailwind for that framework, such as Create Ract App, for example.

Following as the documentation describes, after creating the project, we need to execute the following commands:

# installing tailwind
npm install -D tailwindcss postcss autoprefixer

# initializing tailwind
npx tailwindcss init -p

This will create two new files which need to be edited to something similar to:

// file tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
};

Note that this default configuration assumed the project sctructure points is the same as the original structure created by Vite, when the Vite project was initialized

/* file index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

/* your css code goes here*/

Remember to install the VS Code Tailwind extension if not installed and install the corresponding prettier extension for Tailwind, using the command:

npm install -D prettier prettier-plugin-tailwindcss

After installing the plugin above, it's recommended to create a configuration file with the name prettier.config.mjs, as shown below:

// file prettier.config.mjs
export default {
  plugins: ['prettier-plugin-tailwindcss'],
};

After this setup is done, it's time to start the project with:

# run vite project
npm run dev

Basic component styling with Tailwind CSS:

To start and test if Tailwind was sucessfully installed, we can make use of one of the pre-defined Tailwind classes on any coded component, by making use of the prop className as shown below:

function ComponentWithTailwind() {
  return (
    <div>
      <h1 className='text-xl text-yellow-500 font-semibold'>
        The H1 was customized with Tailwind Classes
      </h1>
    </div>
  );
}

export default ComponentWithTailwind;

Working with colors:

Using pre-deifined colors

When using Tailwind pre-defined color schemes, it's important to notice that the class text-yellow-500 (for example) is mapped to the yellow color shown in the documentation, where the color name refers to the color scheme and the number refers to the shade of that specific color.

A similar class can be used to set the background color, replacing text- by bg- with the same attributes, so using bg-yellow-500 would set the background color to the color yellow, mapped to the shade itensity of 500.

Generally, when working with a layout, the best practice is to select a gray color scheme and a color to be used as the color of the brand. For the project which is being developed in this couse, the color schemes selected where stone as and yellow as the main brand color.


Text Styling:

In Tailwind, to customize the font size and font weight we make use of the classes:

  1. text-nn, where nn makes reference to any of the pre-defined sizes listed in the Tailwind documentation, to set the font-size css property;
  2. font-nn, where nn makes reference to any of the pre-defined weights listed in the Tailwind documentation, to set the font-weight property;
  3. tracking-nn, where nn makes reference to any of the pre-defined spacing listed in the Tailwind documentation, to set the letter-spacing property.

In case any of the default values are not enough, it's possible to set an arbitrary value by making use of square brackets, as shown below, to change the property value to a different value.

<!-- some html code -->
<!--
  Here we use class for HTML files, but it would be className for JSX files.
  
  This technique is called escape hatch, where we can "escape" from Tailwind's rigid classes by providing a non predefined custom value to the ANY of the Tailwind classes
-->
<p class="tracking-[2rem]">Some paragraph with 2rem spacing between letters</p>
<!-- some more html code -->

Box model with Tailwind CSS:

The css box model is based on both margin, padding and borders as we already know. In order to make use of Tailwind's classes, we can use:

  1. mb-nn to set the bottom margin (nn is a number of any pre-defined values of Tailwind, where the alternative escape hatch can be used aswell)
  2. mt-nn to set the top margin
  3. ml-nn to set the left margin
  4. mr-nn to set the right margin
  5. mx-nn to set both the left and right margin
  6. my-nn to set both the top and bottom margin
  7. m-auto to centralize HTML elements
  8. pb-nn to set the bottom padding
  9. pt-nn to set the top padding
  10. pl-nn to set the left padding
  11. pr-nn to set the right padding
  12. px-nn to set both the left and right padding
  13. py-nn to set both the top and bottom padding
  14. border-direction to set a border of 1px on the direction defined by direction
  15. border-direction-nn to set a border of nnpx on the direction defined by direction
  16. border-direction-nn border-color-shade to set a border of nnpx on the direction defined by the direction, with the color and shade specified by both color and shade parameters on the second border definition/declaration
  17. space-direction-nn, used on the parent HTML element, to set space between elements on the direction defined by direction with the size defined by nn
  18. block to set the css display property to block
  19. flex to set the css display property to flex
  20. grid to set the css display property to grid
  21. hidden to set css display to none

NOTES:

  1. Notice that the documentation list all other classes not covered here, so it's highly advised that when making use of this, always having the documentation opened for references and additional information.
  2. More about the display properties later topics.

Responsive layouts:

By default, Tailwind comes with 5 breakpoints, which are mobile-first, meaning they are breakpoints with min media queries.

This means that when working with Tailwind, the best pratice is to work with mobile layouts.

The classes used to make use of those breakpoints are:

  1. sm - screens with 640px minimum
  2. md - screens with 768px minimum
  3. lg - screens with 1024px minimum
  4. xl - screens with 1280px minimum
  5. 2xl - screens with 1536px minimum

The way this works is by prefixing the breakpoint classes to any class that is being used on the layout.

<!-- some HTML code-->
<p classe="sm:text-yellow-500">
  This text will be shown as yellow on screens which are above 640px width
</p>
<!-- some more HTML code-->

Notice that it's not a best practice to simple define breakpoints for styling randomly, but only where the layout breaks or "go buggy", meaning that sometimes, breakpoints may need to be customized and this customization can be done as described on the documentation or making use of the escape hatch technique, by prefixing classes with:

  1. min-[nn] to set the minimum value of the breakpoint as nn
  2. max-[nn] to set the maximum value of the breakpoint as nn

Tailwind Flexbox:

As already discussed, to convert a div into a flex container by setting the display property of the div to flex, all we need to do is to add the class flex to that div.

<!-- some html code-->

<div class="flex">
  <p>Paragraph one</p>
  <p>Paragraph two</p>
</div>

<!-- some more html code-->

To align and justify items inside a flex-box while using Tailwind, we make use of the classes:

  1. item-nn to align the items vertically, where the nn is the direction of alignment
  2. justify-nn to align the items horizontally, where nn is the method of spacing flexbox uses (between, center, around, etc;)
<!-- some html code-->

<!-- This creates a flexbox, with it's contents vertically aligned to the center and justifying them making use of the space-between value justify-content's css property -->
<div class="flex items-center justify-between">
  <p>Paragraph one</p>
  <p>Paragraph two</p>
</div>

<!-- some more html code-->

For more specifications about the flex class, check the official documentation


Tailwind Grid:

To use grids with Tailwind, in a way similar to what was done with the flex-box, the class grid needs to be placed as a class of the parent container element which will be set as a grid container, while specifying the grid height, and optionally the number of rows, columns, gap and width.

The snippet of code below will create a basic layout that fills the screen, while keeping the top and bottm rows to take just the necessary space to fit it's content and the middle row to full up the missing part of the screen

<!-- some html code here-->
<div class="grid h-screen grid-rows-[auto_1fr_auto]">
  <header>Some header to be displayed on row #1 of the grid</header>
  <main>The main content of the page</main>
  <footer>A footer to be displayed on the bottom of the page</footer>
</div>
<!-- some more html code here-->

For more specifications about the grid class, check the official documentation


States and transitions:

Hover state:

To change the style when an HTML element is being hovered, all we need to do is to prepend the hover class to the new styles that should be applied to the element when it's hovered, like in the snippet of code below:

<h1 class="text-red-100 hover:bg-blue-100 hover:text-yellow-500">Some H1 text</h1>

Animations:

In order to apply animations with Tailwind CSS, we make use of the transition-XX property, where XX needs to be replaced by the name of the property we wish to set the transition. The code below specifies some color transition effects when a button is hovered:

<button
  class="inline-block bg-red-500 hover:bg-yellow-300 transition-colors duration-300"
>
  Animated button with Tailwind
</button>

Focus state:

The focus state can be changed by prepending the focus: class to target the focus CSS property and set the desired styling to the element when it's on focus. The example below changes the text color of the previous button when it's focused while also removing it's outline and setting some "shadows" effect to improve accessiblity for users.

<button
  class="inline-block bg-red-500 hover:bg-yellow-300 transition-colors duration-300 focus:bg-slate-200 focus:outline-none focus:ring focus:ring-slate-200 focus:ring-offset-2"
>
  Animated button with Tailwind
</button>

Active state:

To customize the state of when an element is active (for examplem a button being clicked), we repeat the process done with the focus state, making use of the active class. The snippet of code below, shows how to set up some state changes to previously defined button, by changing how it looks like when clicked:

<button
  class="inline-block bg-red-500 hover:bg-yellow-300 transition-colors duration-300 focus:bg-slate-200 focus:outline-none focus:ring focus:ring-slate-200 focus:ring-offset-2 active:ring active:ring-slate-900 active:ring-offset-2 active:text-red-400 active:bg-slate-900"
>
  Animated button with Tailwind
</button>

Disabled state:

By prepending the disabled class it's possible to customize the desired CSS properties when a disabled state is setup to an specific element.

<button
  class="inline-block bg-red-500 hover:bg-yellow-300 transition-colors duration-300 focus:bg-slate-200 focus:outline-none focus:ring focus:ring-slate-200 focus:ring-offset-2 active:ring active:ring-slate-900 active:ring-offset-2 active:text-red-400 active:bg-slate-900 disabled:cursor-not-allowed"
  disabled
>
  Animated button with Tailwind
</button>

Those as simple examples of state customization which can be done with Tailwind. Always remember to check the documentaion for deep details!


Styling form elements:

Input elements:

Placeholder:

If we desire to change the appearance of an placeholder pseudo-element, the only specific requirement is to prepend the class placeholder to any customization to be applied to it:

<input placeholder="Just a placeholder..." class="placeholder:text-blue-300" />

Checkboxes:

To style checkboxes, applying some color to the it when it's checked, we make use of the class accent-xx-nn, where xx refers to the color name to be used and nn references the shader of the selected color:

<input type="checkbox" class="h-4 w-4 accent-red-400" name="check" />
<label for="check">Some label for a checkbox</label>

Styles reusability with @apply:

In Tailwind, it's possible to create layers with css styles which can be reused with the @apply definition.

To create one or more layers with Tailwind, we add the @layer on a CCS file, just like show below:

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  /* css definitions in tailwind sintax goes here */
  .customClass {
    @apply bg-yellow-200 border border-slate-400 sm:focus:ring /* other tailwind sinxes...*/;
  }
}
<h1 class="customClass">H1 with customClass applied with Tailwind</h1>
<button class="customClass">
  Button with customClass applied with Tailwind
</button>

Just keep in mind that making use of this technique should be the exception, not the rule. Best React practices suggests that we create a custom React component and reuse those components as it's been done all over the course.


Styles reusability with React Components:

To follow the best practices for React, all we need to do is to create a custom component with all the Tailwind CSS classes and then reuse that component where it's needed. The snippets below show how to make a resuable component with Tailwind CSS.

// file ReusableH1Component.jsx
function ReusableH1Component({ children }) {
  return <h1 className='px-4 py-3 bg-yellow-300 text-red-400'>{children}</h1>;
}
// file App.jsx
import ReusableH1Component from 'path/to/ReusableH1Component';

function App() {
  return (
    <>
      <ReusableH1Component>
        This is the reusable component instance 1
      </ReusableH1Component>
      <ReusableH1Component>
        This is the reusable component instance 2
      </ReusableH1Component>
    </>
  );
}

Absolute positioning, z-index and more:

In order to work with positioning, refer the documentation for postion and z-index.


Setting a custom font-family:

Tailwind is a very flexible styling library. Even though not going deep into this topic, it's time to edit the Tailwind configuration file so we can leanr now to set some defaults to the project using the configuration file.

The snippet of code below, is a simple example of how to setup some custom patterns with Tailwind. For more details about customization, it's always a good practice to check the documentation, using the default configuration file as reference.

// file tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    fontFamily: {
      // this is a custom font added to the configuration
      sansation: 'Sansation, sans-serif',
      //this will replace every sans-serif fonts used in the application
      sans: 'Arial, sans-serif',
    },
    colors: {
      teal: {
        500: #16b2ab
      }
    },
    extend: {},
  },
  plugins: [],
};

Notice that by creating custom configurations like that will (in the example) override all the defauls set to fontFamily and colors in Tailwind. In case it's necessary to preserve the defaults, the custom settings should be placed inside the extend obejct of the configuration file:

// file tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
 content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
 theme: {
   fontFamily: {
     // this is a custom font added to the configuration
     sansation: 'Sansation, sans-serif',
     //this will replace every sans-serif fonts used in the application
     sans: 'Arial, sans-serif',
   },
   extend: {
     colors: {
       teal: {
         500: #16b2ab
       }
     },
   },
 },
 plugins: [],
};

To use that custom font, all we need to do is to make use of the class font-xx, where xx is the name of the custom front (or any of the predfeined fonts) added to the configuration file above, as in the example below:

<h1 class="font-sansation">A simple H1 with the custom Sansation font</h1>
⚠️ **GitHub.com Fallback** ⚠️