Styles API

What is Styles API

Styles API is a set of props and techniques that allows you to customize styles of any element inside Mantine component inline or with theme object. All Mantine components that have styles support Styles API.

Styles API selectors

Every Mantine component that supports Styles API has a set of elements names that can be used to apply styles to inner elements inside the component. For simplicity, these elements names are called selectors in Mantine documentation. You can find selectors information under Styles API tab in component documentation.

Example of Button component selectors:

SelectorStatic selectorDescription
root.mantine-Button-rootRoot element
loader.mantine-Button-loaderLoader component, displayed only when loading prop is set
inner.mantine-Button-innerContains all other elements, child of the root element
section.mantine-Button-sectionLeft and right sections of the button
label.mantine-Button-labelButton children

You can use these selectors in classNames and styles both in component props and in theme.components:

import { Button, createTheme, MantineProvider } from '@mantine/core';

function ClassNamesDemo() {
  return (
    <Button
      classNames={{
        root: 'my-root-class',
        label: 'my-label-class',
        inner: 'my-inner-class',
      }}
    >
      Button
    </Button>
  );
}

function StylesDemo() {
  return (
    <Button
      styles={{
        root: { backgroundColor: 'red' },
        label: { color: 'blue' },
        inner: { fontSize: 20 },
      }}
    >
      Button
    </Button>
  );
}

const theme = createTheme({
  components: {
    Button: Button.extend({
      classNames: {
        root: 'my-root-class',
        label: 'my-label-class',
        inner: 'my-inner-class',
      },
      styles: {
        root: { backgroundColor: 'red' },
        label: { color: 'blue' },
        inner: { fontSize: 20 },
      },
    }),
  },
});

function ProviderDemo() {
  return (
    <MantineProvider theme={theme}>
      <Button>Button</Button>
    </MantineProvider>
  );
}

classNames prop

With classNames prop you can add classes to inner elements of Mantine components. It accepts object with keys as element names and values as classes:

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)}
    />
  );
}

classNames in theme.components

You can also define classNames in theme.components to apply them to all components of specific type:

import { useState } from 'react';
import { TextInput, MantineProvider, createTheme } from '@mantine/core';
// Styles are the same as in previous example
import classes from './Demo.module.css';

const theme = createTheme({
  components: {
    TextInput: TextInput.extend({
      classNames: {
        root: classes.root,
        input: classes.input,
        label: classes.label,
      },
    }),
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <App />
    </MantineProvider>
  );
}

Components CSS variables

Most of Mantine components use CSS variables to define colors, sizes, paddings and other properties. You can override these values by with a custom CSS variables resolver function in theme.components or by passing it to vars prop.

You can find CSS variables information under Styles API tab in component documentation. Example of Button component CSS variables:

SelectorVariableDescription
root--button-bgControls background
--button-bdControl border
--button-hoverControls background when hovered
--button-colorControl text color
--button-radiusControls border-radius
--button-heightControls height of the button
--button-padding-xControls horizontal padding of the button
--button-fzControls font-size of the button
--button-justifyControls justify-content of inner element

Example of custom CSS variables resolver function used to add more sizes to Button component:

import { Button, rem, Group, MantineProvider, createTheme } from '@mantine/core';

const theme = createTheme({
  components: {
    Button: Button.extend({
      vars: (theme, props) => {
        if (props.size === 'xxl') {
          return {
            root: {
              '--button-height': rem(60),
              '--button-padding-x': rem(30),
              '--button-fz': rem(24),
            },
          };
        }

        if (props.size === 'xxs') {
          return {
            root: {
              '--button-height': rem(24),
              '--button-padding-x': rem(10),
              '--button-fz': rem(10),
            },
          };
        }

        return { root: {} };
      },
    }),
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <Group>
        <Button size="xxl">XXL Button</Button>
        <Button size="xxs">XXS Button</Button>
      </Group>
    </MantineProvider>
  );
}

styles prop

styles prop works the same way as classNames, but applies inline styles. Note that inline styles have higher specificity than classes, so you will not be able to override them with classes without using !important. You cannot use pseudo-classes (for example, :hover, :first-of-type) and media queries inside styles prop.

import { Button, rem } from '@mantine/core';

function Demo() {
  const gradient =
    'linear-gradient(45deg, var(--mantine-color-pink-filled) 0%, var(--mantine-color-orange-filled) 50%, var(--mantine-color-yellow-filled) 100%)';

  return (
    <Button
      radius="md"
      styles={{
        root: {
          padding: rem(2),
          border: 0,
          backgroundImage: gradient,
        },

        inner: {
          background: 'var(--mantine-color-body)',
          color: 'var(--mantine-color-text)',
          borderRadius: 'calc(var(--button-radius) - 2px)',
          paddingLeft: 'var(--mantine-spacing-md)',
          paddingRight: 'var(--mantine-spacing-md)',
        },

        label: {
          backgroundImage: gradient,
          WebkitBackgroundClip: 'text',
          WebkitTextFillColor: 'transparent',
        },
      }}
    >
      Gradient button
    </Button>
  );
}

styles prop usage

Some examples and demos in the documentation use styles prop for convenience, but it is not recommended to use styles prop as the primary means of styling components, as classNames prop is more flexible and has better performance.

Styles API based on component props

You can also pass a callback function to classNames and styles. This function will receive theme as first argument and component props as second. It should return object of classes (classNames) or styles (styles).

You can use this feature to conditionally apply styles based on component props. For example, you can change TextInput label color if the input is required or change the input background color if input has error:

import cx from 'clsx';
import { MantineProvider, createTheme, TextInput } from '@mantine/core';
import classes from './Demo.module.css';

const theme = createTheme({
  components: {
    TextInput: TextInput.extend({
      classNames: (_theme, props) => ({
        label: cx({ [classes.labelRequired]: props.required }),
        input: cx({ [classes.inputError]: props.error }),
      }),
    }),
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <TextInput required label="Required input" placeholder="Required input" />
      <TextInput error label="Input with error" placeholder="Input with error" mt="md" />
    </MantineProvider>
  );
}

Static classes

Every component that supports Styles API also includes static classes that can be used to style component without using classNames or styles props. By default, static classes have .mantine-{ComponentName}-{selector} format. For example, root selector of Button component will have .mantine-Button-root class.

You can use static classes to style component with CSS or any other styling solution:

.mantine-Button-root {
  background-color: red;
}

Static classes prefix can be changed with classNamesPrefix on MantineProvider.

Components classes

Classes of each component are available in Component.classes object. For example, you can find Button classes in Button.classes:

KeyClass
rootm-77c9d27d
innerm-80f1301b
labelm-811560b9
sectionm-a74036a
loaderm-a25b86ee
groupm-80d6d844

You can use these classes to create components with the same styles as Mantine components:

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

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