ReactHustle

How to Style MUI Components with TailwindCSS inside a NextJS Project

Jasser Mark Arioste

Jasser Mark Arioste

How to Style MUI Components with TailwindCSS inside a NextJS Project

Hello, hustlers! In this tutorial, you'll learn how to style MUI Components using TailwindCSS Classes inside a NextJS project.

Introduction #

MUI is a popular library of React components, TailwindCSS is a popular choice for styling components, and NextJS is a very popular choice for a React framework. Wouldn't it be great if we could integrate these technologies together?

Final Output #

Here's the final output. A switch component styled using TailwindCSS classes.

NextJS MUI TailwindCSS Tutorial Final Output

Tutorial Objectives #

  1. Learn how to Setup MUI and TailwindCSS in NextJS
  2. Create a component from @mui/base library so that it's styled with TailwindCSS instead of the default.

Step 1 - NextJS with MUI #

First, we'll have to set up MUI with NextJS, then we'll install TailwindCSS afterward. I already created a previous tutorial on how to set up MUI with NextJS so we'll continue from that tutorial. I suggest you do the previous tutorial and then continue to Step 2 of this tutorial.

Or, if you want to skip the previous tutorial, we can use the code from the previous tutorial as a NextJS starter template. Run the following command and this will give you a NextJS project with MUI pre-installed:

npx create-next-app -e https://github.com/jmarioste/nextjs-mui-typescript-starter my-project

Step 2 - Installing TailwindCSS #

Next, let's install TailwindCSS into our project. Run the following commands to install the prerequisites and initialize tailwind:

# terminal
yarn add -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

After this step, you should see the tailwind.config.js file in your root project directory.

Step 3 - Modifying tailwind.config.js #

Next, we need to modify the tailwind.config.js file for MUI and TailwindCSS to work correctly. You can read more about it here in the MUI documentation. Copy the code below to your tailwind.config.js file.

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./app/**/*.{js,ts,jsx,tsx,mdx}",
    "./pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./components/**/*.{js,ts,jsx,tsx,mdx}",

    // Or if using `src` directory:
    "./src/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  corePlugins: {
    preflight: false,
  },
  important: "#__next",
  theme: {
    extend: {},
  },
  plugins: [],
};
1234567891011121314151617181920

Step 4 - Modifying styles/globals.css #

Next, let's modify globals.css so that it includes the tailwind classes.

// styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
1234

After this, we should be able to use TailwindCSS for MUI components.

Step 5 - Installing @mui/base package #

Next, let's install the @mui/base package so that we'll have access to MUI's unstyled components. This way, we'll have complete control over the styling of these components.

yarn add @mui/base

All the base MUI components are available on mui.com/base.

Step 6 - Creating a Custom Switch Component #

For this tutorial, we'll create a custom <Switch/> Component. First, let's create a completely unstyled switch component. Start by creating the file, src/compnents/MySwitch.tsx:

import { SwitchUnstyled, SwitchUnstyledProps } from "@mui/base";

const MySwitch = (props: SwitchUnstyledProps) => {
  return (
    <>
      <SwitchUnstyled
        {...props}
        // available elements inside SwitchUnstyled that we can style
        slotProps={{
          root(state) {},
          input(state){},
          thumb(state){},
          track(state){},
        }}
      />
    </>
  );
};
export default MySwitch;
12345678910111213141516171819

Explanation:

We are using the SwitchUnstyled component. The slotProps property lets us know which elements we can style. For the switch component, we can style the following: root, input, thumb, and track. If we check the rendered output it renders these 4 elements in the HTML document:

Unstyled switch component

Next, let's style all these elements one by one.

Step 7 - Styling the root slot/element #

First, let's install a utility package called classnames. This will help us toggle tailwind CSS classes depending on the state of the component. Run the command below:

yarn add classnames

For the root element, we'll define some basic properties such as the height and width of the switch. We'll also tone down the opacity to 40% if the state is disabled. We use the classnames package to toggle the opacity.

// src/components/MySwitch.tsx
import { SwitchUnstyled, SwitchUnstyledProps } from "@mui/base";
import classNames from "classnames";

const MySwitch = (props: SwitchUnstyledProps) => {
  return (
    <>
      <SwitchUnstyled
        {...props}
        // slotProps = available elements inside SwitchUnstyled that we can style
        slotProps={{
          root(state) {
            return {
              className: classNames({
                "inline-block relative w-10 h-6 rounded-lg m-2": true,
                "opacity-[40%] cursor-not-allowed": state.disabled,
              }),
            };
          },
        }}
      />
    </>
  );
};
export default MySwitch;
12345678910111213141516171819202122232425

Step 8 - Styling the thumb slot/element #

The thumb element is the small element that moves left and right if the switch is checked or not.

const MySwitch = (props: SwitchUnstyledProps) => {
  return (
    <>
      <SwitchUnstyled
        {...props}
        // slotProps = available elements inside SwitchUnstyled that we can style
        slotProps={{
          ...
          thumb(state) {
            return {
              className: classNames({
                "absolute block w-4 h-4 rounded-sm top-[4px] left-[4px] transition-all duration-150 ease-in-out bg-white":
                  true,
                "translate-x-4": state.checked,
              }),
            };
          },
        }}
      />
    </>
  );
};
export default MySwitch;
1234567891011121314151617181920212223

Step 9 - Styling the input slot/element #

Next, let's style the input element. The input element is of type "checkbox" by default so we'll have to hide that so that it doesn't show to the user.

const MySwitch = (props: SwitchUnstyledProps) => {
  return (
    <>
      <SwitchUnstyled
        {...props}
        // slotProps = available elements inside SwitchUnstyled that we can style
        slotProps={{
          //...
          input(state) {
            return {
              className: classNames({
                "absolute w-full h-full z-[1] top-0 left-0 opacity-0 margin-0":
                  true,
                "cursor-pointer": !state.disabled,
                "cursor-not-allowed": state.disabled,
              }),
            };
          },
        }}
      />
    </>
  );
};
export default MySwitch;
123456789101112131415161718192021222324

Step 10 - Styling the track slot/element. #

Next, let's style the track slot. This is the blue/gray background of the switch component. 

import { SwitchUnstyled, SwitchUnstyledProps } from "@mui/base";
import classNames from "classnames";

const MySwitch = (props: SwitchUnstyledProps) => {
  return (
    <>
      <SwitchUnstyled
        {...props}
        // slotProps = available elements inside SwitchUnstyled that we can style
        slotProps={{
          //...
          track(state) {
            return {
              className: classNames({
                "w-full h-full block rounded-sm": true,
                "bg-indigo-500": state.checked,
                "bg-gray-500": !state.checked,
              }),
            };
          },
        }}
      />
    </>
  );
};
export default MySwitch;
1234567891011121314151617181920212223242526

Step 11 - Demo #

Now it's time for some demos. First, let's render our <Switch/> components in pages/index.tsx:

// pages/index.tsx
import type { NextPage } from "next";
import MySwitch from "../src/components/MyButton";

const Home: NextPage = () => {
  return (
    <div className="container mx-auto">
      <MySwitch />
      <MySwitch defaultChecked />
      <MySwitch disabled />
      <MySwitch defaultChecked disabled />
    </div>
  );
};

export default Home;
12345678910111213141516

Here's the output:

A MUI Switch Component styled with TailwindCSS classes

That's basically it!

Full Code #

The full code is available at GitHub: jmarioste/nextjs-mui-tailwindcss-typescript-starter

Conclusion #

You learned how to set up MUI with TailwindCSS and NextJS. More importantly, you learned how to use unstyled MUI components and style the respective elements inside them with TailwindCSS classes.

If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.

Resources #

Credits: Image by Roger Sexton from Pixabay

Share this post!

Related Posts

Disclaimer

This content may contain links to products, software and services. Please assume all such links are affiliate links which may result in my earning commissions and fees.
As an Amazon Associate, I earn from qualifying purchases. This means that whenever you buy a product on Amazon from a link on our site, we receive a small percentage of its price at no extra cost to you. This helps us continue to provide valuable content and reviews to you. Thank you for your support!
Donate to ReactHustle