Nick Kinlen
Nick Kinlen

Reputation: 1406

Material-UI: Using makeStyles and CSS-In-JS to target library elements styles

I'm using Material-UI and building a form using makeStyles and CSS-In-JS to do the styling. I have a form from the Material-UI library that I am trying to style. I'm trying to figure out how to target classes that come from the library's form element and overwrite the styles.

Here is the form and the Material-UI class I'm trying to target (the form's first text input field's before tag):

enter image description here

I want to change the text field's border-bottom property. Here is what I've attempted. Look at the underline class in the CSS and the form's first text input:

const useStyles = makeStyles((theme) => ({
    root: {
      display: 'flex',
      width: '100%',
      display: 'flex',
      alignItems: 'center'
    },
    container: {
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        height: '100vh'
    },
    paper: {
        padding: theme.spacing(2),
        display: 'flex',
        justifyContent: 'center',
        color: 'snow',
        background: 'salmon'
    },
    form: {
        background: 'salmon',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'flex-start',
        height: '50vh',
        width: '50%'
    },
    customInput: {
        background: 'black'
    },
    underline: {
        '&:before': { 
            borderBottom: '10px solid green'
        },
      },
  }));
  
  export default function FormOne() {
    const classes = useStyles();

    return (
    <Grid container className={classes.container}>
        <Grid item xs={12} md={6}>
            <Paper elevation="5" className={classes.paper}>
                <Formik
                    initialValues={{
                    email: '',
                    password: '',
                    }}

                    validate={values => {
                        const errors = {};
                        if (!values.email) {
                            errors.email = 'Required';
                        } else if (
                            !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
                        ) {
                            errors.email = 'Invalid email address';
                        }
                        return errors;
                    }}

                    onSubmit={(values, { setSubmitting }) => {
                    setTimeout(() => {
                        setSubmitting(false);
                        alert(JSON.stringify(values, null, 2));
                    }, 500);
                    }}
                >
                    {({ submitForm, isSubmitting }) => (
                        <Form className={classes.form}>
                            <Field
                                component={TextField}
                                name="email"
                                type="email"
                                label="Email"
                                fullWidth="true"
                                variant="filled"
                                size="small"
                                color="primary"
                                className={classes.underline}
                            />
                            <br />
                            <Field
                                component={TextField}
                                type="password"
                                label="Password"
                                name="password"
                                fullWidth="true"
                                variant="filled"
                                size="small"
                                color="secondary"
                            />
                            <br />
                            <Field
                                component={TextField}
                                type="password"
                                label="Password"
                                name="password"
                                fullWidth="true"
                                variant="filled"
                                size="small"
                                color="primary"
                            />

                            {isSubmitting && <LinearProgress />}
                            <br />

                            <Button
                                variant="contained"
                                color="primary"
                                disabled={isSubmitting}
                                onClick={submitForm}
                                className={classes.button}
                                >
                                Submit
                            </Button>
                        </Form>
                    )}
                </Formik>
            </Paper>
        </Grid>
    </Grid>
    );
  }

Normally when I use this approach to styling if I include const classes = useStyles(); in my function I can then use className={classes.nameOfClass} on the element and then target that element in makeStyles and I can style elements. This works perfectly for custom elements I'm styling but does not work for overwriting Material-UI library classes.

How can I target .MuiFilledInput-underline:before in makeStyles and customize the styles?

Upvotes: 0

Views: 3852

Answers (2)

Fernando Gomes
Fernando Gomes

Reputation: 443

You can do like @hotpink told, but this way you are going to change only the style of the element in this component (here for more details), but there is a better way to do it, if you want these changes to be applied to all elements along your project:

const theme = createMuiTheme({
  overrides: {
    MuiButton: {
      root: {
        fontSize: '1rem',
      },
    },
  },
});

In the above example we change the css for the global class, you can see how we overrides the root class from the MuiButton element, this way all buttons are going to have the fontSize set to 1rem. You can see the elements classes in the component API page of the component. Here an example

You can see the full docs with a lot of tutorials here and I recommend you to read how to use the ThemeProvider here

Upvotes: 0

hotpink
hotpink

Reputation: 3226

<Field classes={{ underline: classes.underline }} />

and

underline: {
  '&:before': {
    borderBottom: '10px solid green',
  },
},

The API docs for every component will let you know how to target specific DOM elements

Upvotes: 1

Related Questions