The Ultimate MUI CircularProgress Example: Size, Color, Centering

The Material UI CircularProgress component is a quick way to give the user visual feedback while waiting for loading.

It can be challenging to get the centering just right when the CircularProgress is nested in a component. Furthermore, the color prop is limited to MUI theme or color object values. We will explore how to get these details perfect when customizing the component.

Here’s what we will build:

MUI CircularProgress indicator
MUI CircularProgress indicator

My tutorial is based on this MUI documentation example.

Full code and related links are in the Resources section.

Material UI CircularProgress Size

The MUI CircularProgress component has a built-in size prop. This prop is a quick way to specify the width and height of the component. Here’s how size: 80 renders in the DOM:

MUI CircularIndicator Size Prop
MUI CircularIndicator Size Prop

The width and height are critical for centering the indicator inside of a component.

Material UI CircularProgress Centering

The CircularProgress component is centered by setting negative margin top and margin left values. This is a manual process that requires knowledge of the component’s size.

In my example I set the CircularIndicator size to a const so I could use it in a calculation for margin.

const indicatorSize = 80;

<CircularProgress
  size={indicatorSize}
  sx={{
    position: 'absolute',
    top: '50%',
    left: '50%',
    marginTop: `${-indicatorSize/2}px`,
    marginLeft: `${-indicatorSize/2}px`
  }}
/>

Notice how I had to convert my margin values to string with ‘px’. If I passed just a number value, MUI tries to convert it to a theme margin value. Even a number as high as 40 or 80 gets converted to a theme spacing value.

Since we want the CircularIndicator to be centered, we adjust it ‘backwards’ by half it’s height and width.

Material UI CircularProgress Color

The CircularIndicator has a color prop. However, it only accepts string versions of theme values (i.e. ‘secondary.main’) and values from ‘@mui/material/colors’.

If you want a custom color, use the sx prop color value. The color prop is affecting the SVG that’s used to render the circle.

Most likely you won’t want to set background color. This should be transparent because background color is applied to the root which is a span that is rotated to achieve the animation effect.

Resources

Additional Links:

Full Code:

import * as React from "react"
import { Box, Button, CircularProgress } from "@mui/material";

const indicatorSize = 80;

export default function CustomProgressIndicator() {
  const [loading, setLoading] = React.useState(false);
  const timer = React.useRef<number>();

  const handleClick = () => {
    if (!loading) {
      setLoading(true);
      timer.current = window.setTimeout(() => {
        setLoading(false);
      }, 2000);
    }
  };

  return (
  <Box sx={{ m: 1, position: 'relative', display: 'flex', justifyContent: 'center' }}>
    <Button
      variant="contained"
      disabled={loading}
      onClick={handleClick}
      sx={{width: 200, height: 100}}
    >
      Submit Results
    </Button>
    {loading && (
      <CircularProgress
        size={indicatorSize}
        //color='yellow'
        sx={{
          position: 'absolute',
          top: '50%',
          left: '50%',
          marginTop: `${-indicatorSize/2}px`,
          marginLeft: `${-indicatorSize/2}px`,
          color: 'gold'
        }}
      />
    )}
  </Box>
  );
}
Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.