Muhi Logo Text
Work With MeAboutTestimonialsBlog

MUI TextField: How to Customize Variants, Colors & Styles

Learn how to utilize the variants to customize TextField colors & styles in Material UI (MUI) and React including border, label, text color, and more.

Last updated on February 04, 2024

react
mui
MUI TextField Colors

Customizing TextField colors is an essential part of building a beautiful UI. MUI TextField component is not just an input field, but it’s a wrapper that contains multiple elements like the label, input, text helper, error and more. That’s why styling it is a bit different than a regular input field. In this tutorial, we will learn how to customize the colors of the TextField component in Material UI (MUI) and React including the border, label, and text colors for different variants.

The classes that we will use to customize the TextField styles and colors are based on the variant prop. So to find the class we need, we will have to choose the variant first. Let’s go through the different variants and see how we can customize the colors and styles for each one.

Outlined Variant

The outlined variant is the default variant for the TextField component. It has a border around the input field and a label that floats above the input when the user starts typing. To customize the colors of the TextField with the outlined variant, there are three main classes that we can use:

  • MuiOutlinedInput-root: The root class for the input field.
  • MuiInputLabel-outlined: The class for the label.
  • MuiOutlinedInput-notchedOutline: The class for the border.

In the following example, we’re going to override the default colors and styles using the sx prop.

Outlined Custom Styles

import React from "react";
import TextField from "@mui/material/TextField";

export default function OutlinedTextField() {
  return (
    <TextField
      label="Outlined"
      variant="outlined"
      sx={{
        // Root class for the input field
        "& .MuiOutlinedInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          // Class for the border around the input field
          "& .MuiOutlinedInput-notchedOutline": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
        },
        // Class for the label of the input field
        "& .MuiInputLabel-outlined": {
          color: "#2e2e2e",
          fontWeight: "bold",
        },
      }}
    />
  );
}

Outlined Focused State

Although we can see the styles reflected properly in the example above, when focusing on the input field, the changes are not applied. The focused state has it’s own colors and styles and they are directly related to the theme colors. Meaning, if we use the color prop and set it to secondary, we will see the colors of the focused state changes.

...

export default function OutlinedTextField() {
  return (
    <TextField
      label="Outlined"
      variant="outlined"
      color="secondary"
      sx={{
       ...
      }}
    />
  );
}

While it’s correct that the focused state should have different colors (like the primary or secondary color of the theme), we need to apply the other styles to the focused state as well. To do that, we can use the &.Mui-focused class to target the focused state and apply the styles we need.

...

export default function OutlinedTextField() {
  return (
    <TextField
      label="Outlined"
      variant="outlined"
      color="secondary"
      sx={{
        "& .MuiOutlinedInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          "& .MuiOutlinedInput-notchedOutline": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
          "&.Mui-focused": {
            "& .MuiOutlinedInput-notchedOutline": {
              borderColor: "secondary.main",
              borderWidth: "3px",
            },
          },
          "& .MuiInputLabel-outlined": {
            color: "#2e2e2e",
            fontWeight: "bold",
            "&.Mui-focused": {
              color: "secondary.main",
              fontWeight: "bold",
            },
          },
        },
      }}
    />
  );
}

The Mui-focused class is at the root level and that’s why the MuiOutlinedInput-notchedOutline class is nested inside it. Now, when focused, the label, border color and width will change.

Outlined Hover State

After applying the new styles, the default hover state can be effected. We can use the &:hover class to apply the styles we need for the hover state.

...

export default function OutlinedTextField() {
  return (
    <TextField
      label="Outlined"
      variant="outlined"
      color="secondary"
      sx={{
        "& .MuiOutlinedInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          "& .MuiOutlinedInput-notchedOutline": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
          "&.Mui-focused": {
            "& .MuiOutlinedInput-notchedOutline": {
              borderColor: "secondary.main",
              borderWidth: "3px",
            },
          },
          "&:hover:not(.Mui-focused)": {
            "& .MuiOutlinedInput-notchedOutline": {
              borderColor: "#ccc",
            },
          },
        },
        "& .MuiInputLabel-outlined": {
          color: "#2e2e2e",
          fontWeight: "bold",
          "&.Mui-focused": {
            color: "secondary.main",
            fontWeight: "bold",
          },
        },
      }}
    />
  );
}

We also added :not(.Mui-focused) to the hover state to make sure the hover state is not applied when the input is focused.

Filled Variant

The filled variant has a background color, a bottom border and a label that floats within the input when the user starts typing. To customize the colors and styles, there are two main classes that we can use:

  • MuiFilledInput-root: The root class for the input field.
  • MuiInputLabel-filled: The class for the label.

Filled Custom Styles

In the following example, we’re going to override the default colors and styles using the sx prop:

import React from "react";
import TextField from "@mui/material/TextField";

export default function FilledTextField() {
  return (
    <TextField
      label="Filled"
      variant="filled"
      sx={{
        // Root class for the input field
        "& .MuiFilledInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          backgroundColor: "#f4f4f4",
          borderTopLeftRadius: "7px",
          borderTopRightRadius: "7px",
        },
        // Class for the label of the filled input field
        "& .MuiInputLabel-filled": {
          color: "#2e2e2e",
          fontWeight: "bold",
        },
      }}
    />
  );
}

As seen in the code above, using the MuiFilledInput-root class, we can change the background color, border radius and other styles. The MuiInputLabel-filled class is used to change the label styles.

The bottom border is styled separatly as it’s created using the &:before pseudo-element which we can use to change the border color and width.

...

export default function FilledTextField() {
  return (
    <TextField
      label="Filled"
      variant="filled"
      color="secondary"
      sx={{
        "& .MuiFilledInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          backgroundColor: "#f4f4f4",
          borderTopLeftRadius: "7px",
          borderTopRightRadius: "7px",
          "&:before": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
        },
        "& .MuiInputLabel-filled": {
          color: "#2e2e2e",
          fontWeight: "bold",
        },
      }}
    />
  );
}

Filled Focused State

For the focused state, we can use the &.Mui-focused class to target the focused state of the label but the bottom border is also another pseudo-element created using the &:after class in the root class.

In the following example, we’re going to override the default colors and styles for the focused state:

...

export default function FilledTextField() {
  return (
    <TextField
      label="Filled"
      variant="filled"
      color="secondary"
      sx={{
        "& .MuiFilledInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          backgroundColor: "#f4f4f4",
          borderTopLeftRadius: "7px",
          borderTopRightRadius: "7px",
          "&:before": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
          "&:after": {
            borderColor: "secondary.main",
            borderWidth: "3px",
          },
        },
        "& .MuiInputLabel-filled": {
          color: "#2e2e2e",
          fontWeight: "bold",
          "&.Mui-focused": {
            color: "secondary.main",
            fontWeight: "bold",
          },
        },
      }}
    />
  );
}

Filled Hover State

Let’s chnage the background color and the bottom border when hovering over the input field using the &:hover class. Also, we need to make sure the hover state is not applied when the input is focused.

...

export default function FilledTextField() {
  return (
    <TextField
      label="Outlined"
      variant="outlined"
      color="secondary"
      sx={{
        "& .MuiOutlinedInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          "& .MuiOutlinedInput-notchedOutline": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
          "&.Mui-focused": {
            "& .MuiOutlinedInput-notchedOutline": {
              borderColor: "secondary.main",
              borderWidth: "3px",
            },
          },
          "&:hover:not(.Mui-focused)": {
            "& .MuiOutlinedInput-notchedOutline": {
              borderColor: "#ccc",
            },
          },
        },
        "& .MuiInputLabel-outlined": {
          color: "#2e2e2e",
          fontWeight: "bold",
          "&.Mui-focused": {
            color: "secondary.main",
            fontWeight: "bold",
          },
        },
      }}
    />
  );
}

Standard Variant

The standard variant is the most basic variant of the TextField component. It has a bottom border and a label that floats above the input when the user starts typing. To customize the colors and styles, there are two main classes that we can use:

  • MuiInput-root: The root class for the input field.
  • MuiInputLabel-standard: The class for the label.

Standard Custom Styles

In the following example, we’re going to override the default colors and styles using the sx prop:

import React from "react";
import TextField from "@mui/material/TextField";

export default function StandardTextField() {
  return (
    <TextField
      label="Standard"
      variant="standard"
      sx={{
        "& .MuiInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          // Bottom border
          "&:before": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
        },
        // Label
        "& .MuiInputLabel-standard": {
          color: "#2e2e2e",
          fontWeight: "bold",
        },
      }}
    />
  );
}

For the focused and hover states, we will follow the same steps as the filled variant.

Standard Focused State

  • Use the &.Mui-focused class to target the focused state of the label
  • Use the :after pseudo-element to target the focused state of the bottom border
...

export default function StandardTextField() {
  return (
    <TextField
      label="Standard"
      variant="standard"
      color="secondary"
      sx={{
        "& .MuiInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          // Bottom border
          "&:before": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
          // Border on focus
          "&:after": {
            borderColor: "secondary.main",
            borderWidth: "3px",
          },
        },
        // Label
        "& .MuiInputLabel-standard": {
          color: "#2e2e2e",
          fontWeight: "bold",
          "&.Mui-focused": {
            color: "secondary.main",
          },
        },
      }}
    />
  );
}

Standard Hover State

  • Use the &:hover selector to target the hover state of the input field
  • Exclude the hover state when the input is focused using :not(.Mui-focused)
...

export default function StandardTextField() {
  return (
    <TextField
      label="Standard"
      variant="standard"
      color="secondary"
      sx={{
        "& .MuiInput-root": {
          color: "#000",
          fontFamily: "Arial",
          fontWeight: "bold",
          // Bottom border
          "&:before": {
            borderColor: "#2e2e2e",
            borderWidth: "2px",
          },
          // Border on focus
          "&:after": {
            borderColor: "secondary.main",
            borderWidth: "3px",
          },
          ":hover:not(.Mui-focused)": {
            "&:before": {
              borderColor: "#e7e7e7",
              borderWidth: "2px",
            },
          },
        },
        // Label
        "& .MuiInputLabel-standard": {
          color: "#2e2e2e",
          fontWeight: "bold",
          "&.Mui-focused": {
            color: "secondary.main",
          },
        },
      }}
    />
  );
}

Using the Theme

In the examples above, we used the sx prop to override the default colors and styles of the TextField component. Although this is convenient and easy to use, it won’t be the best appraoch as we want to reuse the same styles multiple times across the app. Instead, we can use the theme object to apply the styles globally.

To do that, we can use the createTheme function to create a new theme and then use the ThemeProvider to wrap the app and apply the new theme.

Let’s add styles of all the variants we did to the new theme:

import React from "react";
import TextField from "@mui/material/TextField";
import { ThemeProvider, createTheme } from "@mui/material";

const theme = createTheme({
  components: {
    MuiTextField: {
      styleOverrides: {
        root: {
          // Outlined
          "& .MuiOutlinedInput-root": {
            color: "#000",
            fontFamily: "Arial",
            fontWeight: "bold",
            "& .MuiOutlinedInput-notchedOutline": {
              borderColor: "#2e2e2e",
              borderWidth: "2px",
            },
            "&.Mui-focused": {
              "& .MuiOutlinedInput-notchedOutline": {
                borderColor: "secondary.main",
                borderWidth: "3px",
              },
            },
            "&:hover:not(.Mui-focused)": {
              "& .MuiOutlinedInput-notchedOutline": {
                borderColor: "#ccc",
              },
            },
          },
          "& .MuiInputLabel-outlined": {
            color: "#2e2e2e",
            fontWeight: "bold",
            "&.Mui-focused": {
              color: "secondary.main",
            },
          },
          // Filled
          "& .MuiFilledInput-root": {
            color: "#000",
            fontFamily: "Arial",
            fontWeight: "bold",
            backgroundColor: "#e7e7e7",
            borderTopLeftRadius: "7px",
            borderTopRightRadius: "7px",
            "&:before": {
              borderColor: "#2e2e2e",
              borderWidth: "2px",
            },
            "&:after": {
              borderColor: "secondary.main",
              borderWidth: "3px",
            },
            ":hover:not(.Mui-focused)": {
              "&:before": {
                borderColor: "#e7e7e7",
                borderWidth: "2px",
              },
              backgroundColor: "#f4f4f4",
            },
          },
          "& .MuiInputLabel-filled": {
            color: "#2e2e2e",
            fontWeight: "bold",
            "&.Mui-focused": {
              color: "secondary.main",
            },
          },
          // Standard
          "& .MuiInput-root": {
            color: "#000",
            fontFamily: "Arial",
            fontWeight: "bold",
            "&:before": {
              borderColor: "#2e2e2e",
              borderWidth: "2px",
            },
            "&:after": {
              borderColor: "secondary.main",
              borderWidth: "3px",
            },
            ":hover:not(.Mui-focused)": {
              "&:before": {
                borderColor: "#e7e7e7",
                borderWidth: "2px",
              },
            },
          },
        },
      },
    },
  },
});

export default function CustomThemeTextField() {
  return (
    <ThemeProvider theme={theme}>
      <TextField label="Outlined" variant="outlined" color="secondary" />
      <TextField label="Filled" variant="filled" color="secondary" />
      <TextField label="Standard" variant="standard" color="secondary" />
    </ThemeProvider>
  );
}

Now, when consuming the TextField component anywhere in the application, the custom styles will be applied.

Conclusion

In this tutorial, we learned how to customize the colors and styles of the TextField component in Material UI (MUI) and React. We went through the different variants and saw how to change the border, label, and text colors for each one. We also learned how to apply the styles globally using the theme object.

Bye for now 👋

Complete Code

If you enjoyed this post, I regularly share similar content on Twitter. Follow me @muhimasri to stay up to date, or feel free to message me on Twitter if you have any questions or comments. I'm always open to discussing the topics I write about!

Recommended Reading

Learn how to create a scrollable table with a sticky header and column in React.

react
html
css

Discussion

Upskill Your Frontend Development Techniques 🌟

Subscribe to stay up-to-date and receive quality front-end development tutorials straight to your inbox!

​

No spam, sales, or ads. Unsubscribe anytime you wish.

© 2024, Muhi Masri