DEV Community

Cover image for Setting up Mantine with Tailwind CSS using Emotion cache
Aryaman Sharma
Aryaman Sharma

Posted on • Updated on

Setting up Mantine with Tailwind CSS using Emotion cache

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:

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;
Enter fullscreen mode Exit fullscreen mode

And modify your tailwind config as follows:

 /** @type {import('tailwindcss').Config} */
module.exports = {
  corePlugins: {
    preflight: false, //disabling preflight
  },
  content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

Enter fullscreen mode Exit fullscreen mode

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:

npm install @emotion/react @emotion/cache
Enter fullscreen mode Exit fullscreen mode

OR

yarn add @emotion/react @emotion/cache
Enter fullscreen mode Exit fullscreen mode

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

import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
Enter fullscreen mode Exit fullscreen mode

Then create an emotion cache

function MyApp({ Component, pageProps }: AppProps) {
 const cache = createCache({ key: "mantine", prepend: false });
  return (
    <MantineProvider
      withGlobalStyles
      withNormalizeCSS
      theme={{
        colorScheme: "light",
      }}
    >
      <Component {...pageProps} />
    </MantineProvider>
  );
Enter fullscreen mode Exit fullscreen mode

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:

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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


Top comments (1)

Collapse
 
diivi profile image
Divyansh Singh

Thanks! Was looking for something like this online :D