Loader

Indicate loading state

PackageIcon

Usage

The Loader component supports 3 types of loaders by default: oval, bars, and dots. All loaders are animated with CSS for better performance.

Color
Size
Type
import { Loader } from '@mantine/core';

function Demo() {
  return <Loader color="blue" />;
}

Size prop

You can pass any valid CSS values or numbers to the size prop. Numbers are treated as px, but converted to rem. For example, size={32} will produce the --loader-size: 2rem CSS variable.

Size
import { Loader } from '@mantine/core';

function Demo() {
  return <Loader size={30} />;
}

Adding custom loaders

The Loader component is used in other components (Button, ActionIcon, LoadingOverlay, etc.). You can change the loader type with default props by setting type. You can also add a custom CSS or SVG loader with the loaders default prop.

Custom CSS only loader

Note that in order for the size and color props to work with custom loaders, you need to use the --loader-size and --loader-color CSS variables in your loader styles.

import { MantineProvider, Loader } from '@mantine/core';
import { CssLoader } from './CssLoader';

const theme = createTheme({
  components: {
    Loader: Loader.extend({
      defaultProps: {
        loaders: { ...Loader.defaultLoaders, custom: CssLoader },
        type: 'custom',
      },
    }),
  },
});

function Demo() {
  return (
    <MantineThemeProvider theme={theme}>
      <Loader />
    </MantineThemeProvider>
  );
}

Custom SVG loader

It is recommended to use CSS-only loaders, as SVG-based animations may have the following issues:

  • High CPU usage – the loader may look glitchy on low-end devices
  • Loader animation may not start playing until JS is loaded – users may see a static loader

In your SVG loader, you need to use the --loader-size and --loader-color variables the same way as in CSS-only custom loaders in order for the size and color props to work. Usually, you would need to set width and height to var(--loader-size) and fill/stroke to var(--loader-color).

import { MantineProvider, Loader } from '@mantine/core';
import { RingLoader } from './RingLoader';

const theme = createTheme({
  components: {
    Loader: Loader.extend({
      defaultProps: {
        loaders: { ...Loader.defaultLoaders, ring: RingLoader },
        type: 'ring',
      },
    }),
  },
});

function Demo() {
  return (
    <MantineThemeProvider theme={theme}>
      <Loader />
    </MantineThemeProvider>
  );
}

children prop

The Loader supports the children prop. If you pass anything to children, it will be rendered instead of the loader. This is useful when you want to control the Loader representation in components that use loaderProps, for example Button, LoadingOverlay, Dropzone.

import { useDisclosure } from '@mantine/hooks';
import { LoadingOverlay, Button, Group, Box } from '@mantine/core';

function Demo() {
  const [visible, { toggle }] = useDisclosure(false);

  return (
    <>
      <Box pos="relative">
        <LoadingOverlay visible={visible} loaderProps={{ children: 'Loading...' }} />
        {/* ...other content */}
      </Box>

      <Group justify="center">
        <Button onClick={toggle}>Toggle overlay</Button>
      </Group>
    </>
  );
}