revalidation

How to setup TailwindCSS with Next.JS for performant web applications

TailwindCSS is a powerful CSS framework that eliminates Javascript on the client, unlike many CSS in JS libraries. Learn how to set up and configure TailwindCSS in Next.JS applications for a boost in performance.

CSS code snippet

TailwindCSS is a robust CSS framework for styling web applications. TailwindCSS is a performant CSS framework that runs differently compared to CSS-in-JS frameworks.

With TailwindCSS, CSS computation, compilation, and generation are done once outside the project, during build time, eliminating CSS-related JavaScript from the client-side, unlike in CSS-in-JS frameworks such as styled components, emotion, material UI, and others.

Switching from CSS in JS libraries to TailwindCSS is one of the significant steps to achieving a high-performing web application. It reduces the application's JS footprints, thus reducing the Total Blocking Time and subsequently increasing the Time to Interactive.

TailwindCSS brings back the old way of styling web applications at a much improved and advanced level. It supports the elimination of unused CSS declarations by inspecting the application's source code.

TailwindCSS has enormous features, including support for Dark Mode. Worthy of note is the Just in Time mode, a feature launched in TailwindCSS version 3.

Tailwind supports any web application framework you can think of, including React Frameworks Like Next.JS and Gatsby. This article discusses how to set up Tailwind CSS in NextJS applications and enable critical rendering for the generated CSS.

Next.js, developed by the team at Vercel, is a robust React framework for building web applications. It allows for building hybrid React applications with support for Static Site Generation and Server Side Rendering. In addition, NextJS supports API developments using serverless functions.

In a previous article, I discussed how to optimize NextJS performance through code-splitting, dynamic loading, and preloading of web asset bundles. This guide improves the previous article and shows how to set up TailwindCSS with NextJS to achieve a smaller JS footprint and boost performance.

Setting up TailwindCSS with Next.js

Setting up TailwindCSS in a brand new or already existing Next.Js web application is quite easy and simple. Next.Js comes with the PostCSS Webpack plugin, which plays very well with the TailwindCSS toolings.

Below are the steps on how to set up TailwindCSS with Next.js. Be it a brand new NextJs project or an already existing project. TailwindCSS can also be used with CSS-in-JS libraries.

1. Install TailwindCSS and important PostCSS plugins

Install the latest versions of Tailwind CSS, CSS Autoprefixer plugin, and PostCSS import plugin. CSS Autoprefixer plugin ensures compatibility by performing CSS vendor prefixing for legacy support.

yarn add tailwindcss autoprefixer postcss-import --dev

PostCSS import plugin allows for importing CSS files into another. This is handy, as it makes it possible to style the application in multiple smaller files, which get concatenated into a bigger bundle. This is usually easier to maintain and reason about.

2. Create PostCSS Config File

Create a postcss.config.js file at the root of the project and define the plugins installed in step 1. This file is used to configure PostCSS. For all configuration options, please check out full documentation on how to configure PostCSS.

// postcss.config.js file
module.exports = {
  plugins: {
    'postcss-import': {},
    'tailwindcss/nesting': {},
    tailwindcss: {},
    autoprefixer: {},
  },
};

During the Next.js build, the PostCSS Webpack plugin, which is already configured by the Next.JS team to handle all CSS imports will read and load the plugins defined in the config file above. This way, Tailwind gets incorporated into the project.

3. Create Tailwind Config File

The third step to installing and setting up TailwindCSS in a NextJS application is to create tailwind's config file and configure tailwind. This is a crucial step where Tailwind's core plugins can be enabled or disabled and CSS purging.

Create a tailwind.config.js file at the root of the project and set up CSS purging for production builds.

module.exports = {
  purge: {
    enabled: process.env.NODE_ENV === 'production',
    content: [
      './src/**/*.{js,ts,jsx,tsx}',
    ],
    options: {
      safelist: [],
    },
  },

  darkMode: `class`
};

How you configure Tailwind depends on the project. The important thing is to enable CSS purging. Be advised to specify all project files in the content array that should be considered by Tailwind for purging.

Use the darkMode key to specify if your project supports dark mode. Read the article for more information on tailwind's dark mode support. Tailwind provides a great number of core utility plugins and common settings that are very handy for a good number of projects.

Each Tailwind core plugin can be disabled, configured, and extended through the Tailwind's configuration file. Go here for detailed information on how to configure tailwind, and core plugins, and learn more about other features not discussed here.

4. Create Base Style and import Tailwind CSS

The next step towards setting up Tailwind CSS in Next JS is to create a base CSS file within a styles folder that imports Tailwinds CSS files. This base file is what will be imported into the Next.JS application. Note that the styles folder is kept inside the src folder but can be placed anywhere you want.

Tailwind CSS is divided into 3 layers - namely:

  1. Base Layer
  2. Components Layer
  3. Utility Layer
// src/styles/index.css file
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

Each of the Layers listed above is processed by Tailwind separately and determines the order of the CSS declarations in the final CSS output.

Tailwind includes a Preflight layer that defines CSS rules used to reset browser defaults. It defines CSS for normalizing HTML default styles across major browsers.

The Base Layer can be considered the layer for defining base styles, such as font families, line-heights, heading margins, letter spacings, input placeholder colors, etc.

The components layer is the layer that defines styles for reusable widget components. It touches multiple CSS properties and states or behaviors such as hover states, etc.

Utility Layer defines handy CSS classes for styling specific CSS properties, such as padding, margin, width, height, etc. The Utility Layer should be imported last so that it is possible to override a component style using a utility style.

5. Import Tailwind into Next.JS

The last step in setting up TaillwindCSS with Next.JS is to import the Tailwind CSS into the application. Import the CSS file into Next.js _app.jsx or _app.tsx file.

Create an _app.tsx or _app.jsx file inside the pages folder as shown below and import the index.css file created in step 4.

// src/pages/_app.tsx
import '../styles/index.css';
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

Open up a command terminal and execute yarn dev to start up the development build of the application. On launch, try adding one of Tailwind's core plugin's class names to a div element such as text-center and see it change.

Conclusion

The rise of CSS in JS libraries such as Emotion, Styled-Components, and Material UI came with some drawbacks. It carried a considerable amount of JavaScript footprints and performed a lot of computations on the client-side, degrading time to interactivity.

As a result, there is always a trade-off of performance, a degradation in time to interactivity, and a less improved Total Blocking Time. There is overhead during style rehydration when used in statically generated web applications.

With that said, TailwindCSS removes all these problems by generating CSS once and only during build time with no further computation on the client-side.