Back to all questions

How can I add dynamic CSS styles?

Last updated

data- attributes

If the value that controls dynamic styles is a boolean or a known small union of values, use data- attributes.

First, define data- attributes on the component. In the example below:

  • data-disabled represents boolean disabled attribute. disabled || undefined is required to not add data-disabled="false" attribute when disabled is false and allow styling with &[data-disabled] selector.
  • data-orientation represents orientation prop which can be either horizontal or vertical. In styles you can reference it with &[data-orientation="horizontal"] selector.
import { Box } from '@mantine/core';
import classes from './Demo.module.css';

interface DemoProps {
  disabled: boolean;
  orientation: 'horizontal' | 'vertical';
}

function Demo({ disabled, orientation }: DemoProps) {
  return (
    <Box
      data-disabled={disabled || undefined}
      data-orientation={orientation}
      className={classes.root}
    >
      My demo
    </Box>
  );
}

Then add styles in .module.css file:

.root {
  background: orange;
  display: flex;

  &[data-disabled] {
    background: silver;
  }

  &[data-orientation='horizontal'] {
    flex-direction: row;
  }

  &[data-orientation='vertical'] {
    flex-direction: column;
  }
}

Inline styles

If the value that controls dynamic styles is not represented by a known union of values (for example, value can be any valid CSS color), then you can use inline styles or style props:

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

interface DemoProps {
  fontFamily: string;
  color: string;
}

function Demo({ fontFamily, color }: DemoProps) {
  return (
    <Box style={{ backgroundColor: color }} ff={fontFamily}>
      My demo
    </Box>
  );
}

If you need to customize a deeply nested element, use styles prop instead:

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

interface DemoProps {
  color: string;
}

function Demo({ color }: DemoProps) {
  return (
    <Button styles={{ label: { backgroundColor: color } }}>
      My demo
    </Button>
  );
}

Note that, it is not possible use pseudo-classes (for example, :hover, :first-of-type) and media queries inside the styles prop. For this purpose, use CSS variables with classNames prop.

CSS variables

If none of the methods above works for you (for example, you want to customize, :hover styles based on component prop), use CSS variables with classNames prop.

First, define CSS variables in style or styles prop:

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

interface DemoProps {
  color: string;
}

function Demo({ color }: DemoProps) {
  return (
    <Box style={{ '--demo-hover': color }} className={classes.root}>
      My demo
    </Box>
  );
}

Then reference them in .module.css file:

.root {
  background: orange;

  &:hover {
    background: var(--demo-hover);
  }
}