What you'll learn
  • how to integrate Tailwind CSS in your Webiny project

Overview
anchor

Tailwind CSS is a popular utility-first CSS framework. It allows us to quickly build user interfaces with the help of a plethora of built-in CSS classes and without ever leaving our HTML.

In this guide, we show how you can integrate Tailwind CSS into your Webiny project.

The code that we will cover in this guide can also be found in our GitHub examples repository .

Setting Up Tailwind CSS
anchor

Install Tailwind CSS via Yarn
anchor

Install tailwindcss package and its peer-dependencies using yarn, by running the following command from root of your project:

yarn add -D tailwindcss@npm:@tailwindcss/postcss7-compat@^2.1.2 postcss@^7 autoprefixer@^9

Webiny currently uses Webpack 4 which doesn’t support PostCSS 8 yet. So, we’ll need to install the Tailwind CSS v2.0 PostCSS 7 compatibility build for now as shown above.

Add Tailwind CSS to Webpack Configuration
anchor

In this guide, we integrate Tailwind CSS with the React application that’s located within the Website project application. But, you can use the same approach for other Webiny applications or a custom application for that matter.

Learn more about project applications and packages in the Project Applications and Packages key topic.

We need to add the Tailwind CSS to the postcss plugins inside the Webpack configuration of the application.

Every package in a Webiny application has a webiny.config.ts file that exports the often used development-related commands.

In case of Website (apps/website), it contains the following commands:

  • watch to watch the application
  • build to build the application

Let’s take a brief look at the file content:

apps/website/webiny.config.ts
const { createWatchApp, createBuildApp } = require("@webiny/project-utils");
// Some code is removed for the sake of brevity.

module.exports = {
    commands: {
        async watch(options) {
            (...)

            // Starts local application development.
            const watch = createWatchApp({ cwd: __dirname });
            await watch(options);
        },
        async build(options) {
            (...)

            // Creates a production build of your application, ready to be deployed to
            // a hosting provider of your choice, for example Amazon S3.
            const build = createBuildApp({ cwd: __dirname });
            await build(options);
        }
    }
};

As we can see in the above file, we export an object with commands.watch and commands.build functions, where we use the createWatchApp and createBuildApp helper functions, imported from the @webiny/project-utils package.

Both functions accept the optional overrides property. This is where we’ll assign the necessary Webpack overrides, by assigning a simple callback function to its webpack property.

apps/website/webiny.config.ts
import { createWatchApp, createBuildApp } from "@webiny/project-utils";// Some code is removed for the sake of brevity.
export default {  commands: {      async watch(options) {          // (...)
          // Starts local application development.          const watch = createWatchApp({              cwd: __dirname,               overrides: {                   webpack(config) {                       return require("./applyTailwindToWebpack")(config);                   }               }          });          await watch(options);      },      async build(options, context) {          // (...)
          // Creates a production build of your application, ready to be deployed to          // a hosting provider of your choice, for example Amazon S3.          const build = createBuildApp({              cwd: __dirname,               overrides: {                   webpack(config) {                       return require("./applyTailwindToWebpack")(config);                   }               }          });          await build(options);      }  }};

We use overrides.webpack to add Tailwind CSS in the Webpack configuration in both createWatchApp and createBuildApp commands.

We made this change in both createWatchApp and createBuildApp commands so that we can use Tailwind CSS in both local development and deployed application.

The actual code responsible for making the required modifications to the Webpack configuration is inside the applyTailwindToWebpack file:

apps/website/applyTailwindToWebpack.js
const tailwindcss = require("tailwindcss");
const { traverseLoaders } = require("@webiny/project-utils");

/**
 * A helper function to modify Webpack config.
 */
module.exports = config => {
  /**
   * Traverse all loaders, find `postcss-loader`, and overwrite plugins.
   */
  traverseLoaders(config.module.rules, loader => {
    // `loader` can also be a string, so check for `.loader` property.
    if (loader.loader && loader.loader.includes("postcss-loader")) {
      loader.options.plugins = [...loader.options.plugins(), tailwindcss()];
    }
  });

  return config;
};

Here we export a helper function that modifies Webpack configuration. It takes config as the single argument and returns the new configuration after making some modifications to it.

Inside that function, we use traverseLoaders helper function that we require from @webiny/project-utils package. It traverses all the loaders defined in modules.rules property of the Webpack configuration and passes each one of them to your callback. You can then apply your modifications. In our case, we add Tailwind CSS plugins to the postcss-loader .

Now that we have added Tailwind CSS to Webpack configuration, let’s move on to the next step.

Create Your Tailwind CSS Configuration File
anchor

Next, generate your tailwind.config.js file. From the root of your project run the following command:

npx tailwindcss init

We have created the tailwind.config.js file in the root of Webiny project so that we can share it across all Webiny applications, for example, apps/admin and apps/website.

This creates a minimal tailwind.config.js file at the root of your project:

tailwind.config.js
module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'.
  theme: {
    extend: {}
  },
  variants: {
    extend: {}
  },
  plugins: []
};

Learn more about configuring Tailwind in the configuration documentation .

Now that we have this global configuration, let’s use it in the Website (apps/website) React application by creating a tailwind.config.js file in apps/website/code directory as shown below:

apps/website/tailwind.config.js
// Import config from the project root.
module.exports = require("../../../tailwind.config");

Include Tailwind CSS in Your SCSS
anchor

Now it’s time to include the Tailwind CSS directives in your styles. As most of the styles for Webiny applications are present in apps/theme package, we also include Tailwind CSS styles there.

Open the apps/theme/styles.scss file that exports all theme styles and use the @tailwind directive to include Tailwind CSS base, components, and utilities styles as shown below:

apps/theme/styles.scss
@tailwind base;
@tailwind components;
@tailwind utilities;
(...)

Tailwind CSS swaps these directives out at build-time with all of the styles it generates based on your configured design system.

That’s all! Now, when you start your Website (apps/website) React application locally, by running:

yarn webiny watch apps/website --env dev

Or build it (which happens automatically for you when you deploy your application using webiny deploy command):

yarn webiny deploy apps/website --env {environment}

Tailwind CSS is ready to use in your Webiny project.

Use Tailwind CSS in Website
anchor

Now that we’ve completed the above steps, let’s try adding an example section made with Tailwind CSS as shown below:

apps/website/src/ExampleMadeWithTailwindCSS.tsx
import React from "react";

const ExampleMadeWithTailiwindCSS = () => {
  return (
    <div className="mt-12 -mb-12 bg-gray-50">
      <div className="max-w-7xl mx-auto py-12 px-4 sm:px-6 lg:py-16 lg:px-8 lg:flex lg:items-center lg:justify-between">
        <h2 className="text-3xl font-extrabold tracking-tight text-gray-900 sm:text-4xl">
          <span className="block">Ready to dive in?</span>
          <span className="block text-purple-600">Start your free trial today.</span>
        </h2>
        <div className="mt-8 flex lg:mt-0 lg:flex-shrink-0">
          <div className="inline-flex rounded-md shadow">
            <a
              href="#"
              className="inline-flex items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700"
            >
              Get started
            </a>
          </div>
          <div className="ml-3 inline-flex rounded-md shadow">
            <a
              href="#"
              className="inline-flex items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-purple-600 bg-white hover:bg-indigo-50"
            >
              Learn more
            </a>
          </div>
        </div>
      </div>
    </div>
  );
};

export default ExampleMadeWithTailiwindCSS;

For demonstration purposes, let’s render our newly created React component inside the App component:

apps/website/src/App.tsx
import React from "react";(...)import ExampleMadeWithTailiwindCSS from "./ExampleMadeWithTailwindCSS";
export const App = () => (  <ApolloProvider client={createApolloClient()}>      <BrowserRouter basename={process.env.PUBLIC_URL}>          <PageBuilderProvider>              <ExampleMadeWithTailiwindCSS />              <Switch>                  <Route path={"*"} component={Page} />              </Switch>          </PageBuilderProvider>      </BrowserRouter>  </ApolloProvider>);

If we did everything correctly, at the top of the page, we should be able to see the new section we just created:

Website demo using tailwindcssWebsite demo using tailwindcss
(click to enlarge)

FAQ
anchor

Can I Include Tailwind CSS Directives in Website (app/website) React Application Directly?
anchor

Yes, you can include the directives directly in the main style file of your React application. For example, you can directly add the directives to (apps/website/src/App.scss) file for the Website application.

We chose to include it in the apps/theme package for guide because it’s being used in all React applications of a Webiny project. As a result, we don’t have to include these directives in every React application.

Why Are We Not Using Webpack V5 in a Webiny Project?
anchor

We are working on the Webpack upgrade .