The Ultimate MUI Switch Example: Color, onChange, More

The Material UI Switch component is has the same functionality as a checkbox while providing a more tangible look and feel. We can customize anything we want with the Switch, including the color, size, track and thumb.

Here’s the Switch example that we will create. I will include DOM screenshots to show what classes are needed for nested selectors.

MUI Switch Component Color
MUI Switch Component Color

The Resources section has full code and related article links.

Material UI Switch Icon and DOM

The MUI Switch component doesn’t actually use an icon. It is instead created with a “track” and a “thumb”, both of which are styled spans.

For example, the thumb is a span with 50% border radius.

MUI Switch Thumb DOM
MUI Switch Thumb DOM

If you need to change the look of the Switch, the MuiSwitch-switchBase, MuiSwitch-thumb, and MuiSwitch-track are important classes to target with selectors.

Material UI Switch Thumb Color

The thumb can be styled by targeting either the specific thumb class or the root class MuiSwitch-switchBase.

MUI adds a class called Mui-checked when the Switch is checked. I targeted this class to style the thumb only when it was checked.

"& .MuiSwitch-switchBase.Mui-checked": {
  color: "green"
}

Material UI Switch Track Color

The Switch track was more challenging to target than the Switch thumb.

There were two quirks:

  • I needed to target an invisible Mui-checked+ class. This was not visible in the DOM but was visible in the dev tools styles area
  • I also needed to target MuiSwitch-track and MuiSwitch-switchBase.

Here’s a screenshot of the invisible DOM class:

Mui-checked+ class
Mui-checked+ class

Here’s example code for setting the track color. Notice I had to target background color.

"& .MuiSwitch-switchBase.Mui-checked+.MuiSwitch-track": {
  backgroundColor: 'lightgreen'
}

Material UI Switch Hover

Hover worked well on the Switch. I targeted the hover pseudo-class at the root level, and then targeted the nested MuiSwitch-switchBase class.

This applies a hover color only to the thumb. It also likely tries to apply to the track, but the track needs a more specific selector. Also, strangely, in the screenshot in the last section the track does not seem to have MuiSwitch-switchBase in the DOM but it has it in the styles section as part of a selector.

"&:hover .MuiSwitch-switchBase": {
  color: 'brown'
}

Material UI Switch onChange and Value

The Switch onChange behaves exactly like the Checkbox. Here we see the change handler take the new checked field from the handler and apply it to the state.

Be careful not to use the event.target.value field. In Checkboxes and Switches, this only has a value of on. Even when the Switch is not selected, the value is still on.

const [state, setState] = React.useState({
  pickles: true,
  mustard: false,
  salt: false
});

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  setState({
    ...state,
    [event.target.name]: event.target.checked
  });
  console.log(event.target.value); //don't use this
}

Resources

Related Posts:

Full React code for this tutorial:

import * as React from "react";
import FormLabel from "@mui/material/FormLabel";
import FormControl from "@mui/material/FormControl";
import FormGroup from "@mui/material/FormGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";
import Paper from "@mui/material/Paper";

const switchStyle = {
  borderRadius: 2,
  "& .MuiSwitch-switchBase.Mui-checked": {
    color: "green"
  },
  "& .MuiSwitch-switchBase.Mui-checked+.MuiSwitch-track": {
    backgroundColor: 'lightgreen'
  },
  "&:hover .MuiSwitch-switchBase": {
    color: 'brown'
  },
}

export default function SwitchForm() {
  const [state, setState] = React.useState({
    pickles: true,
    mustard: false,
    salt: false
  });

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setState({
      ...state,
      [event.target.name]: event.target.checked
    });
    console.log(event.target.value);
  }

  const { pickles, mustard, salt } = state;

  return (
    <form>
      <Paper sx={{ padding: 4, display: 'flex', justifyContent: 'center' }}>
        <FormControl
          component="fieldset"
          sx={{ m: 3 }}
          variant="standard"
        >
          <FormLabel component="legend">Choose your lunch order.</FormLabel>
          <FormGroup>
            <FormControlLabel
              control={
                <Switch
                  checked={pickles}
                  onChange={handleChange}
                  name="pickles"
                  sx={switchStyle}
                />
              }
              label="Pickles"
            />
            <FormControlLabel
              control={
                <Switch
                  checked={mustard}
                  onChange={handleChange}
                  name="mustard"
                  sx={switchStyle}
                />
              }
              label="Mustard"
            />
            <FormControlLabel
              control={
                <Switch
                  checked={salt}
                  onChange={handleChange}
                  name="salt"
                  sx={switchStyle}
                />
              }
              label="Salt"
            />
          </FormGroup>
        </FormControl>
      </Paper>
    </form>
  );
}

The FormControlLabels can also be used to wrap Radio components.

MUI Switch Component Docs

Share this post:

Leave a Comment

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