How to Style the Material-UI Autocomplete Component

The Material-UI Autocomplete component and its Popper component can be styled by targeting built-in MUI styling APIs.

In this demo I’ll show the selectors required for styling the Autocomplete component. I’ll do basic styling such as font size, border, hover color. An important characteristic of the Autocomplete component is that it has a Popper that is not a DOM child of Autocomplete. This means we need to create a custom Popper in order to properly target it with a class selector (I’ll show this in the code later in the article).

Here’s the final product after targeting the label, the selected text (with a renderInput component), the Popper, and adding hover. Normally you wouldn’t want this wild color scheme, but I’ve set the colors so that each piece stands out for learning purposes.

Autocomplete with hover, color in the renderInput and Popper, borders and more

If you need to add custom components or modify the layout of the label and option text, read about Autocomplete’s getOptionLabel, renderInput, and renderOption props here.

***UPDATE for MUI 5: Material-UI moved to a new styling API where styling is applied using the sx prop. If you are using MUI v5, simply insert the styling code directly into the sx prop instead of using makeStyles and classes. Read my guide to the MUI sx prop to learn more.

A link to the Code Sandbox with full React code is in the Resources section.

Hover Action

The Popper component is composed of a div which wraps a ul element and all children li elements. It’s separate in the DOM from the Autocomplete elements which makes it tricky to target.

I created a custom Popper component to get around this difficulty. I was then able to apply a class to the CustomPopper, and inside the class I targeted the MUI class .MuiAutocomplete-listbox that gets applied to Autocomplete Poppers.

Inside of this class, I added the & :hover psuedo-class selector.

//styles
root: {
  "& .MuiAutocomplete-listbox": {
    "& :hover": {
      color: "brown"
    }
  }
}

//Custom Popper
const CustomPopper = function (props) {
  const classes = useStyles();
  return <Popper {...props} className={classes.root} placement="bottom" />;
};

//return JSX
<Autocomplete
  //...skipping a few props
  PopperComponent={CustomPopper}
/>

I go into more detail about the Popper component here, including a DOM screenshot.

Font Size, Border, Border Radius, and Text Color

We have two areas of text that we may want to style: the renderInput and label, and the Popper.

In the previous section, I discussed why I created a custom Popper. Now that we can style the Popper, adding font size, border, and text color is simple.

//style
root: {
  "& .MuiAutocomplete-listbox": {
    border: "2px solid grey",
    minHeight: 400,
    color: "green",
    fontSize: 18,
    //hover discussed above
    "& li": {
      //list item specific styling
      border: "2px solid green",
      borderRadius: 4
    }
  }
}

The .MuiAutocomplete-listbox selector targets the ul in the DOM. We can apply li specific styling with the & li selector. I added a border with this method. It could also be used to apply nth-child styling to the list items.

The renderInput is used to specify a component that contains the selected item’s text. In this example I used a TextField. This impacts the selectors that we need to use for styling the label and Input text.

//styling
textfield: {
  "& .MuiInputBase-input.MuiAutocomplete-input": {
    color: "blue",
    fontSize: 18
  },
  "& #custom-autocomplete-label": {
    //or could be targeted through a class
    color: "brown"
  }

}

//return JSX
<Autocomplete
  id="custom-autocomplete"
  renderInput={(params) => {
    return (
      <TextField
        //A few other params...
        className={classes.textfield}
      />
      );
  }}
/>

I created a class called textfield and inside it I targeted .MuiInputBase-input.MuiAutocomplete-input. The first part of this selector is specific to TextFields (they are composed of Input components) and the second is specific to components passed as the renderInput for Autocomplete. This allowed me to style the color and font size of the selected text.

I then noticed in the DOM that the label had an id that was derived from the Autocomplete component’s id: custom-autocomplete-label. I used this to select the label.

Clear Button

I decided the “cancel” button in the TextField Input (it only shows on hover) should also be styled blue. In the same class I added the following:

textfield: {
  "& .MuiButtonBase-root.MuiAutocomplete-clearIndicator": {
    color: "blue"
  }
}

Notice how even the indicator has a specific class applied by Material-UI since it is inside the Autocomplete.

Resources

Code Sandbox Link

An alternative method of styling the Popper would be to attempt an override in the theme overrides object. Using this method, there would be no need to create a custom Popper.

Share this post:

Leave a Comment

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