Setting up Mantine with Tailwind CSS using Emotion cache
Tags: tailwindcss, mantine, emotion, frontend
Published: 2023-06-07 13:25:28

## Working with Mantine and Tailwind CSS

If you have tried setting up Mantine and Tailwind in your project, you would have faced this issue where mantine and tailwind styles end up conflicting with each other. As a result it introduces several unwanted behaviours like your buttons disappearing and only showing when hovered over.

## Cause

The reason this issue arises is mantine's styles getting overridden by tailwinds. Specifically, tailwinds preflight styles.
These preflight styles are applied by default by tailwind in order to normalize styles across different browsers. As a result mantine's style aren't applied correctly

## Solution

In order to resolve this issue, one solution would be to disable these preflight styles 
completely. 

Here is how you would implement in your Next.js app:
 ```tsx
import "../styles/globals.css";
import { MantineProvider } from "@mantine/core";
import type { AppProps } from "next/app";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <MantineProvider
      withGlobalStyles
      withNormalizeCSS //Instructing mantine to apply necessary CSS reset or noramlization styles in your application
      theme={{
        colorScheme: "light",
      }}
    >
      <Component {...pageProps} />
    </MantineProvider>
  );
}

export default MyApp;
 ```
 
 And modify your tailwind config as follows:
 ```ts
 /** @type {import('tailwindcss').Config} */
module.exports = {
  corePlugins: {
    preflight: false, //disabling preflight
  },
  content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

 ```
 This will disable preflight styles applied by tailwind to solve your issue.
 
  You can follow this approach in your react projects as well.

But it might not be the solution you require as it has it's own caveats like
  1. Tailwind CSS's preflight styles include a CSS reset or normalization that establishes a consistent baseline across browsers. Disabling preflight will impact the baseline styles implemented by tailwind CSS.
  2. It may result in a divergence from the default styling provided by CSS. If you have a high dependency on default styles provided by CSS, disabling preflight will sure shot hit your design consistency

***
## Using Emotion Cache 
Emotion.js is a CSS-in-JS library for styling your react/next components.
Mantine uses emotion under the hood. Emotion cache is a caching system provided by Emotion Library. It caches your styles in memory which is used in subsequent renders for your app. We will use this emotion cache in order to prepend Mantine's style so that they are applied after the tailwind's preflight styles

Lets see how to implement this approach:

Assuming you have a Next.js/React Project setup with tailwind and mantine.

  You can follow the steps for each of them here:
  
 Tailwind
   Next.js: https://tailwindcss.com/docs/guides/nextjs
   React.js: https://tailwindcss.com/docs/guides/create-react-app
 
 Mantine
   Next.js: https://mantine.dev/guides/next/
   React.js: https://mantine.dev/guides/cra/
   
To implement emotion cache, we need to get dependencies:
```bash
npm install @emotion/react @emotion/cache
```
OR
```bash
yarn add @emotion/react @emotion/cache
```

Now, In your \_app.jsx/tsx import the CacheProvider and createCache respectively. In react you can perform these steps in your App.js

```ts
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
```

Then create an emotion cache 

```tsx
function MyApp({ Component, pageProps }: AppProps) {
 const cache = createCache({ key: "mantine", prepend: false });
  return (
    <MantineProvider
      withGlobalStyles
      withNormalizeCSS
      theme={{
        colorScheme: "light",
      }}
    >
      <Component {...pageProps} />
    </MantineProvider>
  );
  ```
  
When creating the cache we pass in two things, key and a boolean option called prepend.
The key is used by emotion to identify the cache. And prepend option plays an important role of
The prepend option lets us control the order in which the styles are injected in the page.
This would help in resolving the issue by fixing the order in which the styles are applied between mantine and tailwind.
   if you want Mantine styles to take precedence over Tailwind CSS styles, you can set the prepend option to true for Mantine and false for Tailwind CSS.



After that wrap your components with the CacheProvider passing the cache as a prop to the provider, like so:

```tsx
function MyApp({ Component, pageProps }: AppProps) {
  const cache = createCache({ key: "mantine", prepend: false });
  return (
    <CacheProvider value={cache}>
      <MantineProvider
        withGlobalStyles
        theme={{
          /** Put your mantine theme override here */
          colorScheme: "light",
        }}
      >
        <Component {...pageProps} />
      </MantineProvider>
    </CacheProvider>
  );
}
```

Instead of using CacheProvider, you can pass the cache object to the MantineProvider as well by with the prop called *"emotionCache"*

```ts
function MyApp({ Component, pageProps }: AppProps) {
  const cache = createCache({ key: "mantine", prepend: false });
  return (
    <MantineProvider
      withGlobalStyles
      emotionCache={cache}
      theme={{
        /** Put your mantine theme override here */
        colorScheme: "light",
      }}
    >
      <Component {...pageProps} />
    </MantineProvider>
  );
}
```

And you are ready to go as you styles you apps with Mantine and Tailwind.
Here is the repository with the mentioned implementation:
https://github.com/TheLazron/mantine-tailwind
***