# StylesApi

# Styles API

## What is Styles API

The Styles API is a set of props and techniques that allows you to customize the style of any element
inside a Mantine component – inline or using the [theme object](https://mantine.dev/llms/theming-theme-object.md). All Mantine components that
have styles support the Styles API.

## Styles API selectors

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

Example of the [Button](https://mantine.dev/llms/core-button.md) component selectors:

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

```tsx
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 the `classNames` prop you can add classes to inner elements of Mantine components. It accepts
an object with element names as keys and classes as values:

```tsx
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`](https://mantine.dev/llms/theming-theme-object.md) to apply them to all
components of a specific type:

```tsx
import { useState } from 'react';
import {
  createTheme,
  MantineProvider,
  TextInput,
} 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}>
      {/* Your app here */}
    </MantineProvider>
  );
}
```

## Components CSS variables

Most of Mantine components use CSS variables to define colors, sizes, paddings and other
properties. You can override these values using a custom CSS variables resolver function
in [theme.components](https://mantine.dev/llms/theming-theme-object.md) or by passing it to the `vars` prop.

You can find CSS variables information under the `Styles API` tab in a component's documentation.
Example of [Button](https://mantine.dev/llms/core-button.md) component CSS variables:

Example of a custom CSS variables resolver function used to add more sizes to the [Button](https://mantine.dev/llms/core-button.md) component:

```tsx
// MantineProvider.tsx
import { Button, Group, MantineProvider, createTheme } from '@mantine/core';

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

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

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

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

// Inline.tsx
import { Button, PartialVarsResolver, ButtonFactory, Group } from '@mantine/core';

const varsResolver: PartialVarsResolver<ButtonFactory> = (theme, props) => {
  if (props.size === 'xxl') {
    return {
      root: {
        '--button-height': '60px',
        '--button-padding-x': '30px',
        '--button-fz': '24px',
      },
    };
  }

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

  return { root: {} };
};

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


## styles prop

The `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 the `styles` prop.

```tsx
import { Button } 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
      styles={{
        root: {
          padding: 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 the `styles` prop for convenience, but it is not
> recommended to use the `styles` prop as the primary means of styling components, as the `classNames`
> prop is more flexible and has [better performance](https://mantine.dev/llms/styles-styles-performance.md).

## Styles API based on component props

You can also pass a callback function to `classNames` and `styles`. This function will receive
[theme](https://mantine.dev/llms/theming-theme-object.md) as first argument and component props as second. It should return
an object of classes (for `classNames`) or styles (for `styles`).

You can use this feature to conditionally apply styles based on component props. For example,
you can change the [TextInput](https://mantine.dev/llms/core-text-input.md) label color if the input is required or change the input
background color if the input is wrong:

```tsx
// Demo.tsx
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>
  );
}

// Demo.module.css
.labelRequired {
  color: var(--mantine-color-red-filled);
}

.inputError {
  background-color: var(--mantine-color-red-light);
}
```


## 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](https://mantine.dev/llms/core-button.md)
component will have `.mantine-Button-root` class.

You can use static classes to style a component with CSS or [any other styling solution](https://mantine.dev/llms/styles-css-modules.md#styling-mantine-components-without-css-modules):

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

The prefix of static classes can be changed with `classNamesPrefix` of [MantineProvider](https://mantine.dev/llms/theming-mantine-provider.md#classnamesprefix).

## Components classes

Classes of each component are available in the `Component.classes` object. For example, you can
find the classes of [Button](https://mantine.dev/llms/core-button.md) in `Button.classes`:

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

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

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

## Attributes

You can pass attributes to inner elements of Mantine components using the `attributes` prop.
For example, it can be used to add data attributes for testing purposes:

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

function Demo() {
  return (
    <Button
      attributes={{
        root: { 'data-test-id': 'root' },
        label: { 'data-test-id': 'label' },
        inner: { 'data-test-id': 'inner' },
      }}
    >
      Button
    </Button>
  );
}
```
