How to Style the MUI Select Component and Add Styled Checkboxes

The Material-UI Select component creates a slick menu for users to choose from a list of options. The standard Select uses a dropdown (created from a Popover component) and the native Select uses the html option element.

Both of these variations of the component can have checkboxes enabled. The standard Select can easily have checkboxes enabled, and I will discuss styling the Material-UI Select background color, border, and border radius.

Creating the Select native with checkboxes is quite challenging. In fact, I had to do it using CSS instead of using mui Checkbox.

Here’s what we will be creating. I like to use the ugliest colors I can think of ;). It’s really about exploring the MUI global classes API.

MUI Select Component with Checkboxes
Left: standard multi-select with checkboxes. Right: native select with checkboxes.

Code Sandbox with full React code is in the Resources sections. Here’s a Select component tutorial on customizing dropdown position, default values, multiselect, and more.

Material-UI Select With Checkbox Code

Targeting the proper global classes can be pretty challenging. The styling is all original code. The JSX is is still the same as this example in the docs that I forked my Code Sandbox from.

//styling
selectOptions: {
  "& .MuiListItem-root": {
    borderTop: "1px solid rgb(3,15,252)",
    borderRadius: 8
  },
  "& .MuiListItem-root.Mui-selected, .MuiListItem-root.Mui-selected:hover": {
    backgroundColor: "transparent"
  },
  backgroundColor: "rgb(3,252,244)",
  "& .MuiCheckbox-root": {
    color: "green"
  },
  "& .MuiCheckbox-colorSecondary": {
    "&.Mui-checked": {
      color: "orange"
    }
  }
}

const MenuProps = {
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 5 + ITEM_PADDING_TOP,
      width: 240
    }
  }
};

//inside the component
MenuProps.PaperProps.className = classes.selectOptions;

//in the return JSX
<Select
  multiple
  value={personName}
  onChange={handleChange}
  input={<Input />}
  renderValue={(selected) => selected.join(", ")}
    MenuProps={MenuProps}
  >
    {names.map((name) => (
      <MenuItem key={name} value={name}>
        <Checkbox checked={personName.indexOf(name) > -1} />
        <ListItemText primary={name} />
      </MenuItem>
    ))}
</Select>

The checkboxes are created by looping through an array, but instead of simply rendering text we are rendering a component.

Something important to notice about styling the checkboxes is that I had to apply the selectOptions class to the Menu via renderProps. This is because the Select creates a Popover when the menu is opened, and the Popover is not a child of the Select component in the DOM. The JSS syntax above only works if the class is applied to the Popover or a DOM parent.

The Checkbox is actually a MUI component. This means we can take advantage of the MUI global class API.

MUI-checked

Take a look at the selector for the color in the DOM before I changed the color. We can see that in our selectOptions class, we need to target a child component that has both the .MuiCheckbox-colorSecondary and the .Mui-checked class applied. Explore the JSS syntax I used above to accomplish this.

MUI Select Component Height, Width, Background Color, and Border Styling

The code for these stylings can be found in the previous section, but will be discussed here.

The Select component’s height and width are applied via MenuProps . They are applied to the Paper component inside the Popover, and the Popover (the menu) takes its height and width from its child. The height and width here are affecting the Popover wrapper, not the individual rows.

The Select border and border radius were simpler. They only required targeting .MuiListItem-root in the Popover. The Select menu background color required targeting the .Mui-selected class, which is automatically applied by MUI when the checkbox is selected.

Take a look at the DOM for the Popover generated by the Select component:

MUI Select Component DOM

This shows some of the classes available for targeting with nested selectors.

Material-UI Select Native With Checkbox Code

“Native” Select is created by setting the native prop to true. This creates a component that theoretically has a better user experience on mobile devices.

Once again, the JSX is is still the same as this example in the docs that I forked my Code Sandbox from. The styling for native Select requires targeting DOM elements and pseudo elements instead of MUI global classses.

//styling
nativeSelect: {
  "& .MuiSelect-root": {
    backgroundColor: "rgba(0, 0, 0, 0.08)",
    "& option": {
      padding: "10px 4px",
      //backgroundColor: "rgba(0, 0, 0, 0.08) !important", This had strange DOM effects
      "&::before": {
        content: '"\\2610"',
        width: "1.4em",
        textAlign: "center",
        display: "inline-block",
        fontSize: 24
      }
    },
    "& option:checked": {
      "&::before": {
        content: '"\\2611"',
        fontSize: 24
      }
    }
  }
}

//in the return JSX
<Select
  className={classes.nativeSelect}
  multiple
  native
  value={personName}
  onChange={handleChangeMultiple}
  inputProps={{
    id: "select-multiple-native"
  }}
>
  {names.map((name) => (
    <option key={name} value={name}>
      {name}
    </option>
  ))}
</Select>

I was not able to inject checkbox (input) elements or components into the native Select. However, this SO answer was very helpful in creating the checkboxes through a pure CSS approach.

Also, styling the option elements was challenging. While background color can be set on the Select component (I commented it out in the code above), this created some strange UI looks. The option element cannot have background color directly applied when a focus event happens, which means we are stuck with a blue highlight. However, you may be able to set focus color by setting a background image on focus. Let me know in the comments if you have success with this.

Take a look at the DOM screenshot below of the CSS selectors. The -internal-list-box pseudo element/class was generated by the browser and I was unable to target it.

Checkboxes in native select

My recommendation is simply to push back on a requirement for checkboxes in the native select. It isn’t really designed for such a use case.

Resources

Think you’re a JavaScript expert? Test yourself on these 50 difficult JavaScript questions.

If you want another example of adding Checkboxes to MUI components, here’s how to add Checkboxes in the Treeview component.

Are you looking for training in Material-UI? Check out my review of the best Material-UI course on Udemy, which has 40+ hours of content and a 30-day money back guarantee.

Code Sandbox Link

Docs

Share this post:

4 thoughts on “How to Style the MUI Select Component and Add Styled Checkboxes”

Leave a Comment

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