CSS modules

All Mantine components use CSS modules for styling. It is recommended to use CSS modules in your project as well, but it is not required – Mantine components are fully compatible with any third-party styling solution and native CSS.

Usage

CSS modules are supported out of the box by all major frameworks and build tools. Usually, all you need to do is to create *.module.css file:

/* Button.module.css */
.button {
  color: red;
}

And then import it in your component:

import classes from './Button.module.css';

function Demo() {
  return (
    <button className={classes.button} type="button">
      Button
    </button>
  );
}

How CSS modules work

When you create a *.module.css file, your build tool will generate a unique class name for each class in your file. For example, when you import the following file in your .js/.ts file:

/* Button.module.css */
.button {
  color: red;
}

.text {
  color: blue;
}

You will get an object with unique class names:

import classes from './Button.module.css';

console.log(classes);
// -> Object of scoped class names: key is a class name, value is a generated unique class name
// { button: 'button-Xh3s7ER', text: 'text-js65s3Se' }
// Note that generated class names may vary depending on your build tool

With CSS modules, you do not need to worry about class name collisions, you can use any class name you want.

Mantine components styles

All Mantine components are built with CSS modules, but all styles are bundled before publishing to npm. To include these styles, you need to import @mantine/{package}/styles.css file in your application. Example with @mantine/core package:

import '@mantine/core/styles.css';

By adding this import, you will have all styles of @mantine/core components in your application.

Import styles per component

If you want to reduce CSS bundle size, you can import styles per component. Note that some components have dependencies, for example, Button component uses UnstyledButton component internally, so you need to import styles for both components. You can find a full list of exported styles from @mantine/core package and additional instructions on this page.

import '@mantine/core/styles/UnstyledButton.css';
import '@mantine/core/styles/Button.css';

Adding styles to Mantine components

You can add styles to most of Mantine components using className prop – the same way as you would do with a regular HTML element. To set properties to your theme values, you can use Mantine CSS variables:

Box component with some styles
import { Box } from '@mantine/core';
import classes from './Demo.module.css';

function Demo() {
  return (
    <Box className={classes.box}>
      Box component with <span className={classes.highlight}>some styles</span>
    </Box>
  );
}

To apply styles to inner elements of Mantine components with CSS modules, you can use classNames prop (see Styles API for more information):

import { useState } from 'react';
import { TextInput } from '@mantine/core';
import classes from './Demo.module.css';

function Demo() {
  const [value, setValue] = useState('');
  const [focused, setFocused] = useState(false);
  const floating = focused || value.length > 0 || undefined;

  return (
    <TextInput
      label="Floating label input"
      labelProps={{ 'data-floating': floating }}
      classNames={{
        root: classes.root,
        input: classes.input,
        label: classes.label,
      }}
      onFocus={() => setFocused(true)}
      onBlur={() => setFocused(false)}
      value={value}
      onChange={(event) => setValue(event.currentTarget.value)}
    />
  );
}

Styling Mantine components without CSS modules

All Mantine components are fully compatible with any third-party styling solution and native CSS. There are two main strategies to apply styles with a third-party library:

  • className, classNames, style and styles props
  • with static selectors, for example .mantine-Text-root

Example of applying styles with a utility CSS library:

import { TextInput } from '@mantine/core';

function Demo() {
  return (
    <TextInput
      classNames={{
        root: 'mt-4',
        input: 'bg-red-500 text-white',
      }}
    />
  );
}

Example of applying styles with global CSS:

/* styles.css */

/* Note that these styles are not scoped and
   will be applied to all TextInput components */
.mantine-TextInput-root {
  margin-top: 0.8rem;
}

.mantine-TextInput-input {
  background-color: var(--mantine-color-red-filled);
  color: var(--mantine-color-white);
}

You can combine both approaches to achieve desired results, for example, @emotion/styled and styled-components packages will pass className prop to a given component, and you can use static selectors to style inner elements:

import { Slider } from '@mantine/core';
import styled from '@emotion/styled';

const StyledSlider = styled(Slider)`
  & .mantine-Slider-bar {
    background-color: var(--mantine-color-pink-5);
  }

  & .mantine-Slider-thumb {
    border-color: var(--mantine-color-pink-5);
    background-color: white;
    width: 1.5rem;
    height: 1.5rem;
  }
`;

function Demo() {
  return <StyledSlider defaultValue={40} />;
}

Consider using CSS modules first

CSS modules are the recommended way of styling Mantine components. Before choosing another styling solution, make sure that CSS modules do not fit your needs. Other solutions have limitations, for example:

  • It is hard to customize styles based on data-* attributes when using utility-based CSS libraries
  • It is impossible to style inner elements of Mantine components with static selectors when using styled-components and other similar libraries if component uses Portal because some elements will be rendered outside of the component root and inner elements are not part of the component tree