Search code examples
cssreactjsmaterial-uistylingcss-in-js

MaterialUI TextField : changing background color is not working as it is supposed to


I'm trying to set the background color for TextField components in the app I'm working on, however it seems that when I add style={{background: "rgb(232, 241, 250)"}} to this component with my custom RGB values it displays them on top of the default gray background color.

Background color supposed to be same light blue as in the components above: problem screenshot

  1. I tried to resolve it by just adding the style property to it

  2. Also, by adding makeStyles() to the component and attaching it through className

In both cases, I got this output as on the screenshot above.

  1. I was able to get the correct background color by removing variant=filled or setting it to standard or outlined, but then the padding around the text would be removed.

I don't really understand what is this issue and how it could be actually fixed?

import React from "react";
import {TextField} from "@material-ui/core";

import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles((theme) => ({
     root: {
         background: 'rgb(232, 241, 250)'
      },
}));

export interface InquiryContentInputProps {
   content: string;
   onChange: (content: string) => void;
}

export function InquiryContentInput(props: InquiryContentInputProps) {
   const classes = useStyles();

   return (
       <TextField
          variant="filled"
          // style={{background: "rgb(232, 241, 250)"}}
          className={classes.root}
          fullWidth={true}
          multiline={true}
          rows={5}
          rowsMax={10}
          value={props.content}
          onChange={(e) => props.onChange(e.target.value as string)}
          label="Суть обращения"/>
   )
}

Solution

  • TextField renders several elements -- an outer <div> for the FormControl element, and then within that the InputLabel and the Input element (e.g. FilledInput).

    The className prop on TextField applies that class to the FormControl. The default background color for FilledInput, is rgba(0, 0, 0, 0.09), so this was still being applied over your light blue background on the FormControl.

    You can instead override the background-color on the FilledInput as follows:

    import React from "react";
    import TextField from "@material-ui/core/TextField";
    
    import { makeStyles } from "@material-ui/core/styles";
    
    const useStyles = makeStyles((theme) => ({
      root: {
        "& .MuiFilledInput-root": {
          background: "rgb(232, 241, 250)"
        }
      }
    }));
    
    export default function InquiryContentInput(props) {
      const classes = useStyles();
    
      return (
        <TextField
          variant="filled"
          className={classes.root}
          fullWidth={true}
          multiline={true}
          rows={5}
          rowsMax={10}
          value={props.content}
          onChange={(e) => props.onChange(e.target.value)}
          label="Суть обращения"
        />
      );
    }
    

    Edit filled TextField background

    Another option is to leverage InputProps to specify the className for the input:

    import React from "react";
    import TextField from "@material-ui/core/TextField";
    
    import { makeStyles } from "@material-ui/core/styles";
    
    const useStyles = makeStyles((theme) => ({
      input: {
        background: "rgb(232, 241, 250)"
      }
    }));
    
    export default function InquiryContentInput(props) {
      const classes = useStyles();
    
      return (
        <TextField
          variant="filled"
          InputProps={{ className: classes.input }}
          fullWidth={true}
          multiline={true}
          rows={5}
          rowsMax={10}
          value={props.content}
          onChange={(e) => props.onChange(e.target.value)}
          label="Суть обращения"
        />
      );
    }
    

    Edit filled TextField background (forked)

    Just a follow up question: if I wanted to change the background color scheme on this TextField on focus and hover, would I also do it via some class override in the makeStyles? And what would it be or where could I find the names of those classes?

    There are two main ways to determine the names of the classes:

    1. Inspect the elements in the browser developer tools to see the classes that are added by Material-UI.

    2. Look at the source code. This requires understanding some of how the Material-UI CSS class names are generated.

    In FilledInput you can find the following styles defined (simplifying below to only include the background-color styles):

    export const styles = (theme) => {
      const light = theme.palette.type === 'light';
      const backgroundColor = light ? 'rgba(0, 0, 0, 0.09)' : 'rgba(255, 255, 255, 0.09)';
    
      return {
        /* Styles applied to the root element. */
        root: {
          backgroundColor,
          transition: theme.transitions.create('background-color', {
            duration: theme.transitions.duration.shorter,
            easing: theme.transitions.easing.easeOut,
          }),
          '&:hover': {
            backgroundColor: light ? 'rgba(0, 0, 0, 0.13)' : 'rgba(255, 255, 255, 0.13)',
            // Reset on touch devices, it doesn't add specificity
            '@media (hover: none)': {
              backgroundColor,
            },
          },
          '&$focused': {
            backgroundColor: light ? 'rgba(0, 0, 0, 0.09)' : 'rgba(255, 255, 255, 0.09)',
          },
          '&$disabled': {
            backgroundColor: light ? 'rgba(0, 0, 0, 0.12)' : 'rgba(255, 255, 255, 0.12)',
          },
        },
    

    The keys in this structure (e.g. root) will be converted to class names with the general pattern of Mui${componentName}-${styleRuleKey} (e.g. MuiFilledInput-root). The pseudo-classes (e.g. $focused, $disabled) are documented here and get prefixed with Mui- (e.g. Mui-focused, Mui-disabled).

    You can override the hover and focused colors, by following the same pattern as in the FilledInput source code:

    import React from "react";
    import TextField from "@material-ui/core/TextField";
    
    import { makeStyles } from "@material-ui/core/styles";
    
    const useStyles = makeStyles((theme) => ({
      root: {
        "& .MuiFilledInput-root": {
          backgroundColor: "rgb(232, 241, 250)"
        },
        "& .MuiFilledInput-root:hover": {
          backgroundColor: "rgb(250, 232, 241)",
          // Reset on touch devices, it doesn't add specificity
          "@media (hover: none)": {
            backgroundColor: "rgb(232, 241, 250)"
          }
        },
        "& .MuiFilledInput-root.Mui-focused": {
          backgroundColor: "rgb(250, 241, 232)"
        }
      }
    }));
    
    export default function InquiryContentInput(props) {
      const classes = useStyles();
    
      return (
        <TextField
          variant="filled"
          className={classes.root}
          fullWidth={true}
          multiline={true}
          rows={5}
          rowsMax={10}
          value={props.content}
          onChange={(e) => props.onChange(e.target.value)}
          label="Суть обращения"
        />
      );
    }
    

    Edit filled TextField background (hover and focus)

    I have another follow up question. If I wanted to define those values in the theme (for example, MuiFilledInput for all states including hover and focus), how would I do it? I was able to add it on its regular state right now through adding: const theme = createMuiTheme({ "overrides": { "MuiFilledInput": { "root": { "backgroundColor": 'rgb(232, 241, 250)' } } } }) But I can't add custom background values to the theme for hover and focus

    Here's the syntax for doing these same styles in the theme:

    import React from "react";
    import TextField from "@material-ui/core/TextField";
    
    import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
    
    const theme = createMuiTheme({
      overrides: {
        MuiFilledInput: {
          root: {
            backgroundColor: "rgb(232, 241, 250)",
            "&:hover": {
              backgroundColor: "rgb(250, 232, 241)",
              // Reset on touch devices, it doesn't add specificity
              "@media (hover: none)": {
                backgroundColor: "rgb(232, 241, 250)"
              }
            },
            "&.Mui-focused": {
              backgroundColor: "rgb(250, 241, 232)"
            }
          }
        }
      }
    });
    
    export default function InquiryContentInput(props) {
      return (
        <ThemeProvider theme={theme}>
          <TextField
            variant="filled"
            fullWidth={true}
            multiline={true}
            rows={5}
            rowsMax={10}
            value={props.content}
            onChange={(e) => props.onChange(e.target.value)}
            label="Суть обращения"
          />
        </ThemeProvider>
      );
    }
    

    Edit filled TextField background (hover and focus) via theme