The Complete Guide to Customizing the MUI Rating Component

The Material-UI Rating icon is a quick solution for giving users the ability to input a rating. The component has built-in props for customizing the size, color, and icons.

The component has some interesting customizations and limitations. The props seem to provide all the customization you could want. However, on further examination I found the following limitations:

  • If I use a custom icon I cannot set size using the size prop
  • If I use CSS to change the margin between the icons, the hover-fill no longer applies in the correct area
  • This limits the scale I can apply on hover

My takeaway is that the Rating is a solid component if you use it within the limitations of its built-in styling props.

In this tutorial we will change the icon based on the selected value. This will help us explore custom icons, color, and size in the Rating component.

MUI Rating Icon with Custom Styling
MUI Rating Icon with Custom Styling

There is a Code Sandbox link to a live demo in the Resources section. Full code can be found in the Resources section.

Material-UI Rating Color

If you want to change the Rating’s color, you need to use nested selectors that target the MUI classes applied automatically to the component. The following are the critical classes you need to be aware of:

  • MuiRating-icon
  • MuiRating-iconDecimal
  • MuiRating-iconEmpty
  • MuiRating-iconFilled
  • MuiRating-iconHover
  • MuiRating-iconFocus

The DOM structure is composed of a span that wraps children spans, one child span for each rating icon. MuiRating-icon is the root class. It is applied to the parent span. The children spans are composed of sub-elements that ultimately render the icon.

MUI Rating DOM
MUI Rating DOM

The MuiRating-iconDecimal class is applied when the rating can be incremented by a decimal. The other classes are self-explanatory by their names. If you want to style the color on hover, focus, or any other time, use these classes.

Take a look at the example below where I change the styling on icons that are filled as part of the selected rating and on hover:

<Rating
  sx={{
    "& .MuiRating-iconFilled": {
      color: "blue"
    },
    "& .MuiRating-iconHover": {
      color: "purple"
    }
  }}
/>

Material-UI Rating Size

The Rating component comes with a size prop, and the possible values are small, medium, and large. It works by changing the font size on the span that wraps each icon.

There are two caveats to changing icon size in Rating. First, it doesn’t work if you supply a custom icon using the icon prop. This is surprising because the font size is still changed by the size prop even with custom icons.

The second caveat is that you should not try to adjust size using CSS. If you do, it corrupts the math for spacing the icons and you can get strange outcomes like the below (where I used transform: scale(2.5)).

Don't use CSS for MUI Rating size
Don’t use CSS for MUI Rating size

Material-UI Rating Icon

The Rating icon prop allows for custom filled icons, while the emptyIcon prop allows for custom empty icons (like the greyed icons in the image above).

Customize Rating Icon Count

There is a handy prop for setting the number of icons: max. This accepts a numeric value.

When a user selects a rating, the numeric sequence value is passed to the onChange handler as the second property. In other words, if a user rates at 3/5, the onChange handler receives a value of 3.

Change Icon Based On Selection

I thought it would be interesting to change the icon based on user selection. In my demo, if the user selected 1/5 the icon turned to a sad face. The face looked happier the higher the rating the user selected.

I accomplished this by passing the selected value to an onChange handler, which updated selectedValue (a state value). Then in a useEffect hook I evaluate selectedValue and update icon and emptyIcon accordingly.

You can see full code for this in the Resources section.

A similar alternative is to have the icons be static but set a specific icon for each value. The MUI docs have a demo of this here.

Resources

import * as React from "react";
import Rating from "@mui/material/Rating";
import Typography from "@mui/material/Typography";
import SentimentVeryDissatisfiedIcon from "@mui/icons-material/SentimentVeryDissatisfied";
import SentimentDissatisfiedIcon from "@mui/icons-material/SentimentDissatisfied";
import SentimentSatisfiedIcon from "@mui/icons-material/SentimentSatisfied";
import SentimentSatisfiedAltIcon from "@mui/icons-material/SentimentSatisfiedAltOutlined";
import SentimentVerySatisfiedIcon from "@mui/icons-material/SentimentVerySatisfied";

const customStyle = {
  "& .MuiRating-iconFilled": {
    color: "blue"
  },
  "& .MuiRating-iconHover": {
    color: "purple"
  },
  "& .MuiRating-decimal:hover": {
    transform: "scale(2.5)"
  }
};

export default function CustomRating() {
  const [selectedValue, setSelectedValue] = React.useState(4.8);
  const [icon, setIcon] = React.useState(<SentimentVerySatisfiedIcon />);
  const [emptyIcon, setEmptyIcon] = React.useState(
    <SentimentVerySatisfiedIcon />
  );

  React.useEffect(() => {
    if (selectedValue <= 1) {
      setIcon(<SentimentVeryDissatisfiedIcon />);
      setEmptyIcon(<SentimentVeryDissatisfiedIcon />);
    } else if (selectedValue <= 2) {
      setIcon(<SentimentDissatisfiedIcon />);
      setEmptyIcon(<SentimentDissatisfiedIcon />);
    } else if (selectedValue <= 3) {
      setIcon(<SentimentSatisfiedIcon />);
      setEmptyIcon(<SentimentSatisfiedIcon />);
    } else if (selectedValue <= 3) {
      setIcon(<SentimentSatisfiedAltIcon />);
      setEmptyIcon(<SentimentSatisfiedAltIcon />);
    } else {
      setIcon(<SentimentVerySatisfiedIcon />);
      setEmptyIcon(<SentimentVerySatisfiedIcon />);
    }
  }, [selectedValue]);

  return (
    <>
      <Typography>Icon Changes Based On Rating</Typography>
      <Rating
        sx={customStyle}
        //size="medium"
        defaultValue={selectedValue}
        precision={0.1}
        icon={icon}
        emptyIcon={emptyIcon}
        onChange={(event, value) => {
          setSelectedValue(value);
        }}
      />
    </>
  );
}

Here’s how to customize the MUI Divider text and color.

Here’s a guide to customizing MUI Icons.

MUI Rating Docs

MUI Rating API Docs

Code Sandbox Link

Share this post:

Leave a Comment

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