Material-ui: Is there a way to have global CSS classes?

Created on 30 Oct 2017  路  14Comments  路  Source: mui-org/material-ui

Let's say I have the following in a component:

const styles = theme => ({
  alignRight: {
    "margin-left": "auto"
  }
});

Now, I might want to align something to the right side in some other place too. Using the default css in js system, I then have to define 'alignRight' class in every single component that I want to use it in.

My question is, how can I make the same class available to multiple components without having to declare it everywhere?

The customization page doesn't seem to address this.

docs good first issue styles

Most helpful comment

@kushalmahajan Ok, here are two examples to have global CSS, the first one is fully global, the second one is an hybrid:

import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";

const styles = {
  "@global": {
    ".root": {
      height: 100,
      width: 100,
      backgroundColor: "red"
    }
  },
  foo: {
    "&.bar": {
      height: 100,
      width: 100,
      backgroundColor: "blue"
    }
  }
};

function GlobalClass(props) {
  const { classes } = props;

  return (
    <React.Fragment>
      <div className="root" />
      <div className={`${classes.foo} bar`} />
    </React.Fragment>
  );
}

GlobalClass.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(GlobalClass);

https://codesandbox.io/s/5xxmxkx1wk

capture d ecran 2019-02-13 a 14 55 34


@@kushalmahajan It would be great to document it in our documentation: https://material-ui.com/css-in-js/advanced/#global-css. If you want to submit a documentation pull request, we would be happy to review it!

All 14 comments

I think that you are looking for the @global plugin of JSS. Here is the documentation.

Yeah but that doesn't play well with withStyles, right? There's no way to refer to those "global" classes through the classes object in each component.

@AdityaAnand1 JSS will generate a deterministic class name. You are free to use wherever you like. it's global CSS, like you would do it with the bootstrap class names.

I was looking for a solution to this as well. It's not really a MUI problem, but withStyles seems like the correct approach so maybe it could be tweaked to make this work.

This is the API I'm looking for (it doesn't quite work as is):

import { Theme, WithStyles, createStyles, withStyles } from '@material-ui/core/styles'
import classNames from 'classnames'
import React from 'react'

interface IProps extends WithStyles<typeof globalStyles>, WithStyles<typeof myComponentStyles> {}

// styles defined once per app and used on many components
const globalStyles = ({ spacing }: Theme) =>
    createStyles({
        pushLeft: { marginLeft: spacing.unit },
        pushRight: { marginRight: spacing.unit },
    })
// styles specific to `MyComponent`
const myComponentStyles = () =>
    createStyles({
        root: { color: 'red' },
    })

function MyComponent({ classes }: IProps) {
    // `classes` contains typed global and component CSS classes
    return <div className={classNames(classes.root, classes.pushLeft, classes.pushRight)} />
}

// HOC gets `globalStyles` and `myComponentStyles`.
export default withStyles(globalStyles)(withStyles(myComponentStyles)(MyComponent))

// Figure out a way to wrap this to only make one HOC per Component. Maybe HOF like:
const myWithStyles = createWithStyles(globalStyles)
myWithStyles(myComponentStyles)(MyComponent)

There's no way to refer to those "global" classes through the classes object in each component.

No, you can't. But what's the point, it's global? Here is an example:
https://github.com/mui-org/material-ui/blob/7d2fadfc7b90c958d10ef89a0a3ce58cc7ff939e/packages/material-ui/src/CssBaseline/CssBaseline.js#L8-L17

@oliviertassinari in the linked example you lose type safety of your global CSS classes, no?

@christophercliff Yes, you lose type safety.

What if I have .anyGlobalClass. What do I do in that case?

For that this doesn't work on my component.

className={classNames(classes.ButtonLeft, 'anyGlobalClass')}

@kushalmahajan You have two options. 1. you change the class name generator to have global classnames https://material-ui.com/css-in-js/advanced/#global-css 2. you use the @global syntax of JSS to target global class names. Your example should be working.

yes, I was in fact looking at your example given above for 2nd option i.e.

 const styles = theme => ({ 
 '@global': { 
      '.anyGlobalCss': { ...rules} 
 }

This doesn't works. Then option 1 is in alpha...probably not looking into it.

@kushalmahajan Ok, here are two examples to have global CSS, the first one is fully global, the second one is an hybrid:

import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";

const styles = {
  "@global": {
    ".root": {
      height: 100,
      width: 100,
      backgroundColor: "red"
    }
  },
  foo: {
    "&.bar": {
      height: 100,
      width: 100,
      backgroundColor: "blue"
    }
  }
};

function GlobalClass(props) {
  const { classes } = props;

  return (
    <React.Fragment>
      <div className="root" />
      <div className={`${classes.foo} bar`} />
    </React.Fragment>
  );
}

GlobalClass.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(GlobalClass);

https://codesandbox.io/s/5xxmxkx1wk

capture d ecran 2019-02-13 a 14 55 34


@@kushalmahajan It would be great to document it in our documentation: https://material-ui.com/css-in-js/advanced/#global-css. If you want to submit a documentation pull request, we would be happy to review it!

Sure. Will implement and document this weekend

@kushalmahajan It was taken care by @n-batalha, no need :).

Great!

Was this page helpful?
0 / 5 - 0 ratings