How to Change MUI TextField’s Border Color (Hover, Focus, Overrides, and More)

I spent quite a few hours recently on a seemingly simple task: customizing the border color of a Material-UI TextField when outlined variant and disabled state were applied. The TextField is a complex component to style and I hope others will benefit from the examples presented here.

This post includes MUI v4 and and v5 examples.

MUI TextField disabled state border color
MUI TextField disabled state border color

Here are all the features this post covers:

  • MUI Input border color
  • Disabled TextField border color
  • Outlined variant TextField border color – plus other variants
  • TextField focus color
  • TextField hover color
  • TextField with no border – border: none or standard variant
  • TextField theme border override – uses code marked experimental by MUI team

The Material-UI TextField is composed of several subcomponents, including the Input component.

I will mention whether each example is Material-UI v4 or v5 styling syntax. I use the sx prop in the v5 examples in this post. Here’s a guide to the new styled API if you prefer it over the sx prop.

The MUI v5 syntax is far simpler than v4 syntax. If you have not upgraded yet, I recommend it.

The Resources section has a Code Sandbox link to an example TextField with border color on hover.

Here’s a YouTube video version of this article, or you can watch it below:

Material-UI Input Border Color

The Input component can be used as a stand-alone component in MUI, and it is also a compositional component of the TextField.

The Input does not accept variants, but it does have a color prop. However, the color prop only accepts theme palette colors. This means you need to customize the palette if you want to use this prop with a non-default color.

TypeScript typing for Input color prop
TypeScript typing for Input color prop

Additionally, the prop only styles focus state color, not hover color.

MUI Input Color Prop
MUI Input Color Prop

Styling the Input with a custom border is simple compared to the TextField. There are no nested selectors needed. Take a look at the code:

<Input
  sx={{border: '1px solid green', borderRadius: 1}}
  disableUnderline
  id="basic-input"
/>

Pro tip: use disableUnderline to remove the underline. This removes a :before pseudo-element that renders the underline. Otherwise you will need to target it with a nested selector in order to remove it.

MUI Input Border Color
MUI Input Border Color

Interestingly, the stand-alone Input component does not have classes on it like muioutlinedinput-notchedoutline or muioutlinedinput that we see on the TextField’s Input subcomponent.

Change MUI TextField Border Color in Disabled State

This example uses a simple TextField with outlined variant (the default) and prop disabled: true.

Even if you are using MUI v5, it is worth reading through the original example I created in MUI v4. It includes lots of DOM screenshots, and the composing elements of the TextField didn’t change in the upgrade.

However, I will caution that the method of applying border color is significantly harder in v4 than v5.

Version 4 Syntax

Let’s start with a pretty simple disabled TextField component.

<TextField
disabled
variant='outlined'
label='Text Field 1'
InputProps={{
classes: {
root: classes.root
}
}}
/>

Initially, it seems we should just add a borderColor to our root class in our JSS file:

root: {
borderColor: 'orange'
}

We see it applied in dev tools, yet we don’t see an orange border around the TextField. Unfortunately, targeting the root class applies the borderColor to an inner element of the TextField that doesn’t actually control the border color.

Material-UI TextField DOM
Dev tools with root targeted

So let’s try again via trial-and-error. Let’s select the input element which is a child of the div previously targeted:

//component
InputProps={{
   classes: {
      root: classes.root,
      disabled: classes.disabled
   }
}}

//styles
root: {
   '& $disabled': {
      borderColor: 'orange'
   }
},
disabled: {}

Still no luck. The input is targeted properly, but the border is not yet orange.

Material-UI TextField DOM with disabled state
Dev tools with root and .disabled targeted

Trying again, let’s target the fieldset. It looks promising since it has a class named MuiOutlinedInput-notchedOutline. We target it with the following:

//component
InputProps={{
   classes: {
      root: classes.root,
      disabled: classes.disabled,
      notchedOutline: classes.notchedOutline
   }
}}

//styles
root: {
   '&$disabled $notchedOutline': {
      borderColor: 'orange'
   }
},
disabled: {},
notchedOutline: {}

A couple points about the code above: First, notice that there is no space between & and $disabled. Second, notice that there is a built in class called notchedOutline in the InputProps API that Material UI intends for us to target.

Material-UI TextField DOM with border styling
Successfully overriding MUI Textfield border style

Success!

Version 5 Syntax

Note: There is a new color prop. It accepts theme palette values such as primary and secondary. Like the Input component, the color prop only changes focus color, not hover color.

The key to styling the TextField component is understanding the primary compositional pieces: FormControl, Input, and Fieldset (not a stand-alone component, but rendered as a separate element). Fieldset is only available on the outlined variant.

A common (and unsuccessful) first attempt at changing the TextField border color is setting the sx prop value at the root level:

//Don't do this
<TextField
    sx={{border: "solid black 2px"}}
    id="disabled-basic"
    label="outlined"
    variant="outlined"
    disabled
/>

However, this adds an additional border instead of styling the existing border. The root-level sx styles the FormControl, but we want to change the border on the Input component. Take a close look at the screenshot and notice the rounded second border.

MUI v5 disabled TextField border color
MUI v5 disabled TextField border color

We could style the Input with border: 'none', but it’s better to keep the Input border and update it’s color. Here’s the correct sx syntax:

sx={{"& .MuiOutlinedInput-root.Mui-disabled":{"& > fieldset": {border: '1px solid green'}}}}

It is important to notice that I targeted both MuiOutlinedInput-root and Mui-disabled. Only targeting one class or the other is not specific enough and will be overridden by MUI’s default styling.

Furthermore, I then targeted the nested fieldset component. This is the element that actually has a border on it. See the DOM screenshot below to get a better understanding of this:

MUI Disabled TextField DOM
MUI Disabled TextField DOM

Change MUI TextField Outlined, Filled, and Standard Variant Border Color

I will show only the v5 code for this section.

There are three out-of-the-box MUI TextField variants. The default variant is “outlined”. Here’s a screenshot from the docs of the the three variants with no additional styling:

Outlined Variant

The only variant that has a border is the outlined variant (no surprise there). Here’s the code for styling it:

<TextField
  sx={{
    "& .MuiInputLabel-root": {color: 'green'},//styles the label
    "& .MuiOutlinedInput-root": {
      "& > fieldset": { borderColor: "orange" },
    },
  }}

  variant="outlined"
/>

This code does not use classes specific to the outlined variant, but it does use the fieldset element which is specific to the outlined variant. Also, I added green text color to the label. Here’s how it looks:

MUI Outlined TextField Border Color
MUI Outlined TextField Border Color

It is useful to explore the DOM and see what styling classes are available. The muioutlinedinput-notchedoutline class is applied by default to the fieldset component and can be used as an alternative selector.

Filled Variant

The filled variant requires a less complex nested selector.

<TextField
  sx={{
    "& .MuiInputLabel-root": {color: 'green'},
    "& .MuiFilledInput-input": {border: '1px solid orange', borderRadius: 1}
  }}
  InputProps={{disableUnderline: true}}
  label="filled"
  variant="filled"
/>

Be sure to remove the ‘underline’ that is applied by default. This can be done with the disableUnderline prop we saw on the Input component. However, it must be properly passed via InputProps.

Standard Variant

The standard variant is the simplest of the variants. It is essentially an Input component with extra props available.

<TextField
  sx={{
    "& .MuiInputLabel-root": { color: "green" },
    border: "1px solid green",
    borderRadius: 1
  }}
  InputProps={{ disableUnderline: true }}
  label="standard"
  variant="standard"
/>

Adding a border to the standard variant is just like adding a border to an Input prop.

How to Change MUI TextField Border Radius

If you add a border to the MUI TextField, you may also want to customize the border radius. However, the selector to customize the border radius is different for different TextField variants.

Here’s the border radius code for the “outlined” variant. The outlined variant is also the default:

<TextField
  sx={{
    "& .MuiOutlinedInput-root": {
      "& > fieldset": {

        borderRadius: 4
      }
    }
  }}
  label="outlined"
/>

Notice we have to target the fieldset within the MuiOutlinedInput-root element.

Here’s the border radius code for the filled variant:

<TextField
  sx={{
    "& .MuiFilledInput-root": {
      borderRadius: 4,
      InputProps={{ disableUnderline: true }}
    }
  }}
  id="filled-basic"
  label="filled"
  variant="filled"
/>

Here I only had to target the MuiFilledInput-root element. However, there is a line below the input area that you may want to remove if you add border radius. The line does not shrink properly with the border radius so it is best to remove it. This is accomplished with InputProps={{ disableUnderline: true }}.

The Input component is the simplest to have a custom border radius. Simply pass a border radius value to the sx prop like this: sx={{ borderRadius: 2 }}.

Change MUI TextField Border Color on Focus

Controlling focus state color is similar to controlling disabled state color. The code below is almost the same as the code for the disabled state section.

In MUI v4, I again used the notchedOutline class to give high specificity to the class styling. In v5, this was

Version 4 Syntax

Below is the code for setting focused color. Notice the only difference is that focused takes the place of disabled.

<TextField
   disabled
   variant='outlined'
   label='Text Field 1'
   InputProps={{
      classes: {
         root: classes.root,
         focused: classes.focused,
         notchedOutline: classes.notchedOutline
      }
   }}
/>

//styles
root: {
   '&$focused $notchedOutline': {
      borderColor: 'orange'
   }
},
focused: {},
notchedOutline: {}
Material-UI TextField border hover color
focus state override

Version 5 Syntax

We will apply focus styling by targeting the .Mui-focused class, which is a sibling class of MuiOutlinedInput-root.

<TextField
  sx={{
    "& .MuiOutlinedInput-root.Mui-focused": {
      "& > fieldset": {
borderColor: "orange"
      }
    }
  }}
  id="outlined-basic"
  label="outlined"
  variant="outlined"
/>

Change MUI TextField Hover Border Color

The code for changing hover styling is very similar to the code for disabled and focus styling.

Version 4 Syntax

Hover is a psuedo-class, so the syntax is adjusted to use & instead of $:

<TextField
   disabled
   variant='outlined'
   label='Text Field 1'
   InputProps={{
      classes: {
         root: classes.root,
         notchedOutline: classes.notchedOutline
      }
   }}
/>

//styles
root: {
  '&:hover $notchedOutline': {
    borderColor: 'orange'
  }
},
focused: {},
notchedOutline: {}

Version 5 Syntax

As mentioned above, focus used a built-in MUI class but hover uses a pseudo-class:

<TextField
  sx={{
    width: { sm: 250, md: 350 },
    "& .MuiOutlinedInput-root:hover": {
      "& > fieldset": {
        borderColor: "orange"
      }
    }
  }}
  variant="outlined"
/>

I replicated the cool notched effect in the Bootstrap InputGroup border.

Style MUI TextField with No Border

The easiest way to remove the border from a Material-UI TextField is to use the ‘standard’ variant instead of the default ‘outlined’ variant.

It’s design is minimalist:

MUI Standard Variant TextField
MUI Standard Variant TextField

If you are needing to remove the border from the outlined variant, use the following code:

<TextField
  sx={{
    "& .MuiOutlinedInput-root": {
      "& > fieldset": {
        border: "none"
      }
    }
  }}
  label="outlined"
/>

MUI TextField Theme Override Border Color

The MUI theme is highly customizable and we can override default styling for TextFields. We can even use nested selectors in the overrides.

CAUTION: this uses code marked ‘experimental’ by the MUI team.

The code below includes imports. First, we create a custom theme and pass it to our TextField with a ThemeProvider. Then in the theme, we update the styleOverrides field of the MuiTextField.

import TextField from "@mui/material/TextField";
import {
  createTheme,
  ThemeProvider,
  experimental_sx as sx,
} from "@mui/material/styles";

const customTheme = createTheme({
  components: {
    MuiTextField: {
      styleOverrides: {
        root: sx({
          "& .MuiOutlinedInput-root": {
            "& > fieldset": {
              borderColor: "orange",
            },
          },
        }),
      },
    },
  },
});

export default function CustomTextFieldBorders() {
  return (
    <ThemeProvider theme={customTheme}>
      <TextField label="outlined" />
    </ThemeProvider>
  );
}

Notice the experimental_sx import. I don’t know if the MUI team recommends this object for use in prod.

Otherwise, this code is similar to using a typical TextField with sx. It produces the same result, except that it will apply to all TextFields within the InputProvider.

Resources and Related Links

My MUI course on Udemy is now available!!! Build a full MUI app from beginning to end, learn every aspect of the sx prop, styled API, and the theme, and tackle the most challenging components! Do you want an active Q&A with me?!? Check here for coupons for my MUI course on Udemy.

Read this post for more examples of customizing the TextField component, and here’s how to style the label.

The Autocomplete component commonly uses TextField as its renderInput component. This is a situation where understanding TextField customization can help in many parts of your UI.

Here’s how to set and get values in the MUI TextField.

This Code Sandbox has an example of adding hover to the MUI TextField using the sx prop.

Share this post:

8 thoughts on “How to Change MUI TextField’s Border Color (Hover, Focus, Overrides, and More)”

  1. THANK YOU SO MUCH FOR THIS POST!!!!!!! I have been struggling with this for HOURS and never in a million years would have figured this out without you! THANK YOU!!!

    Reply

Leave a Comment

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