How to override component styles within Mui5 theme? - reactjs

I'm in the process of upgrading from Mui4 to 5.
After upgrading, my index file looks like that (note I'm using JSS, hence the StyledEngineProvider):
function renderApp() {
ReactDOM.render(
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<CssBaseline />
<Typography variant="h2" component="h2">H2 TEST</Typography>
...
</ThemeProvider>
</StyledEngineProvider>,
document.getElementById('root'),
);
}
And my theme:
createTheme({
components: {
MuiTypography: {
defaultProps: {
title: 'test h2 title',
},
styleOverrides: {
root: {
fontSize: '10px',
fontWeight: 500,
},
},
},
},
});
I can see my theme been is used as the "title" attribute is added to my Typography component. But everything within styleOverrides seems to be dropped.
Also, colors added to theme.palette works, but theme.typography.h2 doesn't change any style either. I have the same logic for other components and it doesn't seems to work.
As specified in Styles broken after migrating to v5 I made sure StyledEngineProvider is at the top of the components tree and removed any trace of #material-ui/core (Mui4) from the application.

Following the migration doc, it wasn't clear that the following packages are mandatory even though you use JSS within your application and not emotion. Note that there is no warning whatsoever, for example emotion styles within the theme configuration will simply not be compiled.
You must install the following:
npm install #emotion/react #emotion/styled

Related

Change React Material-UI DataGrid (table) Default Font Size

Using Material-UI DataGrid, the default font in table is too small to see text.
My code is literally a copy/paste of their demo on the page:
https://material-ui.com/components/data-grid/
My fonts are very small in the table. Rest of page not using Mui (menu etc.) are fine.
In Firefox dev tools Inspector I see
Inherited from div:
.MuiDataGrid-root { font-size: 0.875rem; }
Changing that in the browser tool to something like 10px, or disabling it completely, confirms thats the value needing change.
It's being automatically added at end (inline) when compiled so it overwrites my previous style. The silly thing is, I can't find where this is being added.
I've looked at several sites using this same table as examples and none have this issue.
Can someone enlighten me where to look, how to fix the table having incorrect default font size?
I have these relevant bits:
package.json:
"#material-ui/core": "^4.11.0",
"#material-ui/data-grid": "^4.0.0-alpha.6",
"fontsource-roboto": "^3.0.3",
Index.html
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
Abbreviated .jsx code:
import React from 'react';
import { DataGrid } from '#material-ui/data-grid';
const DemoTableMui = () => {
...
const columns = [{ field: 'id', headerName: 'ID', width: 70 } ]
const rows = [{ id: 1, lastName: 'Smith', firstName: 'Jon', age: 35 } ]
return (
<div style={{ height: 600, width: '100%' }}>
<DataGrid rows={rows} columns={columns} pageSize={5} checkboxSelection />
</div>
);
};
export default DemoTableMui
Since the dev tool indicated it is inherited from div I did stuff like:
return (
<div style={{ height: 600, width: '100%', fontSize:25 }}>
...
But nothing had effect. I'm sure the div it is referring to is buried down in the <DataGrid/> component...
Based on OP feedback, putting an answer here.
Isolating the CSS problem.
if you are using a theme, start with the file that has the DIV root. That is where styles are included.
start looking the specific CSS class that is affecting, and instead of changing the value - which won't work as you have already seen.
Make a copy of the CSS class, give it a different name, and set the desired value and then use this new class.
Alternatively (based on the OP update in the comments)
Consider abandoning any usage of themes just use the standard themes such as bootstrap (or react strap, if you are on react js), which wont have these problems.
Themes tend to have a mix of native components and also standard components. In most cases, they will have two folders. one for bootstrap css files and another for theme css files.
Unless you are already experienced with the theme, making changes can become tricky. Use the standard bootstrap components, which use standardized names and hence, no complications.
So the best way to use material-UI IMO is to customize the theme at the root level, and then all of the components should inherit the styling in a uniform kind of way. This is what my App.tsx looks like
import {
createMuiTheme,
MuiThemeProvider
} from "#material-ui/core/styles";
const theme = createMuiTheme({
palette: {
type: 'dark'
},
typography: {
fontSize: 12
},
// overrides: {
// MuiTypography: {
// colorInherit:{
// color: "#fff"
// }
// }
});
function App() {
return (
<MuiThemeProvider theme={theme}>
<LeadPage/>
</MuiThemeProvider>
);
}
export default App;
Setting the typography will trickle down to the class .MuiDataGrid-root.
I left the palette up there which changes the font color of the grid, and the commented out code is a an example of overriding the class at the theme level, in case you need to tweak that grid further. My example would be if you saw .MuiTypography-colorInherit in the debugger.
import { MuiThemeProvider } from "#material-ui/core/styles";
...
import { createTheme } from '#material-ui/core';
export const muiTheme = createTheme({
typography: {
fontFamily: 'Poppins Regular',
},
});
...
<MuiThemeProvider theme={muiTheme}>...</MuiThemeProvider>

How to import and use a custom font in a material-ui theme?

I'm trying to import and use the Yellowtail font (from Google Fonts) in my React app in a Material-UI theme.
As far as i know all google fonts are on npm, I've installed it, with the
npm install typeface-yellowtail --save
command.
I have imported it in App.js, put it in the font-family part of the theme, passed the theme to the MuiThemeProvider, but it does not work. What did I miss?
This is what i have inside of App.js (header contains an AppBar with some grids and body contains only an h1 text for testing)
import React, { Component, Fragment } from 'react';
import Header from './Components/Layouts/Header';
import AppBody from './Components/Layouts/AppBody';
import Footer from './Components/Layouts/Footer';
import { MuiThemeProvider, createMuiTheme } from '#material-ui/core';
import 'typeface-yellowtail';
const theme = createMuiTheme({
typography: {
fontFamily:
'"Yellowtail", cursive',
},
});
class App extends Component {
render() {
return (
<MuiThemeProvider theme={theme}>
<Header />
<AppBody />
<Footer />
</MuiThemeProvider>
);
}
}
export default App;
Instead of installing via npm, you can just first load CSS file.
#import url('https://fonts.googleapis.com/css?family=Yellowtail&display=swap');
Import this CSS file
import './assets/css/yellowtail.css';
Now you don't need to use any #font-face. This can be used with font families like normal.
You are missing three things:
Import the npm package as something
Use the CssBaseline component
Add an override to the object provided to createMuiTheme()
See example:
import React, { Component, Fragment } from 'react';
import Header from './Components/Layouts/Header';
import AppBody from './Components/Layouts/AppBody';
import Footer from './Components/Layouts/Footer';
import { MuiThemeProvider, createMuiTheme, CssBaseline } from '#material-ui/core';
import yellowtail from 'typeface-yellowtail';
const theme = createMuiTheme({
typography: {
fontFamily:
'"Yellowtail", cursive',
},
overrides: {
MuiCssBaseline: {
'#global': {
'#font-face': [yellowtail],
},
},
},
});
class App extends Component {
render() {
return (
<MuiThemeProvider theme={theme}>
<CssBaseline />
<Header />
<AppBody />
<Footer />
</MuiThemeProvider>
);
}
}
export default App;
Example CodeSandbox (MUI v3): https://codesandbox.io/s/late-pond-gqql4?file=/index.js
Example CodeSandbox (MUI v4): https://codesandbox.io/s/pensive-monad-eqwlx?file=/index.js
Notes
MuiThemeProvider changed to ThemeProvider in the transition from Material-UI v3 to v4. If you are on v4, this is the only change needed - this example code otherwise works on both versions.
You must wrap text in Material-UI's Typography component for the font to be used.
There is a much easier way of doing this that doesn't require a .css file or installing any extra packages.
If your font is available over a CDN like Google Fonts then just imported into the root HTML file of your app:
<link
href="https://fonts.googleapis.com/css2?family=Yellowtail&display=swap"
rel="stylesheet"
/>
Then add one line in the Material-UI theme:
const theme = createTheme({
typography: { fontFamily: ["Yellowtail", "cursive"].join(",") }
});
Working codesandbox example with Material-UI v5.
Update: Since #ekkis mentioned I'm adding further details on how to include the Google Font. The following answer assumes you're using Material UI v4.10.1
Install the gatsby-plugin-web-font-loader to install Google font.
Edit gatsby-config.js to include the plugin and the Google font.
module.exports = {
plugins: [
{
resolve: "gatsby-plugin-web-font-loader",
options: {
google: {
families: ["Domine", "Work Sans", "Happy Monkey", "Merriweather", "Open Sans", "Lato", "Montserrat"]
}
}
},
]
}
To use the font, create a file called theme.js in src/components
import {
createMuiTheme,
responsiveFontSizes
} from "#material-ui/core/styles"
let theme = createMuiTheme({
typography: {
fontFamily: [
"Work Sans",
"serif"
].join(","),
fontSize: 18,
}
})
// To use responsive font sizes, include the following line
theme = responsiveFontSizes(theme)
export default theme
Now that you've the theme export, you can use it in your components.
Import theme on to your components. Let's say <Layout /> is your main component.
// src/components/layout.js
/**
* External
*/
import React from "react"
import PropTypes from "prop-types"
import {
ThemeProvider
} from "#material-ui/styles"
import { Typography } from "#material-ui/core"
/**
* Internal
*/
import theme from "./theme"
const Layout = ({ children }) => {
return (
<>
<ThemeProvider theme={theme}>
<Typography variant="body1">Hello World!</Typography>
</ThemeProvider>
</>
)
}
To use Google font in other components, just use
<Typography ...>Some Text</Typography>
As long as these components use as their parent, these components will continue to use the Google Font. Hope this helps.
Old Answer:
Place your text in the Typography component to reflect the Google Font you installed via npm
import { Typography } from "#material-ui/core"
Assume you have some text in <AppBody>
<AppBody>
Hello World!
</AppBody>
The above text should now be changed to
<AppBody>
<Typography variant="body1">Hello World!</Typography>
</AppBody>
Refer Material UI docs for the different variants.
I have define my font in main CSS file(index.css)
#font-face {
font-family: 'mikhak';
src: url(./fonts/mikhak.ttf) format("truetype")
}
and then in the App.tsx I added theme
const theme = createTheme({
typography: {
fontFamily: 'mikhak, Raleway, Arial',
}
});
ReactDOM.render(
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>,
document.getElementById('root')
);
Note that it is for Typography components.
This worked for me:
Install your font as a package using #fontsource on npm, i.e:
npm i #fontsource/work-sans
Add to your _app.js your import, this makes your package (font) accessible globally
const workSans = require('#fontsource/work-sans');
In your theme modify your typography:
...
typography: {
fontFamily: 'Work Sans',
}
...
That's it!
I want to add to #georgeos answer that a small revision of the proposed solution worked for me:
export const theme = createTheme({
...
components: {
MuiCssBaseline: {
styleOverrides: {
'#global': {
'#font-face': [Inter, Nunito],
},
},
},
},
...
});
I also needed to add the following to the app.ts file (source):
function App(){
...
return (
<ThemeProvider theme={theme}>
<CssBaseline enableColorScheme /> <---
...
</ThemeProvider>);
...
}

What does the CssBaseline class do?

I've been wondering what the CssBaseline class in the Material-UI React library does, but I can't seem to find an answer anywhere, and the page I linked doesn't do much explaining about what the class does. Does anyone here know what this component is supposed to do?
CssBaseline is sort of css reset added to the <head /> of your document. If you are familiar with similar approaches like normalize.css which adds some default visual styling to default elements, resets paddings and etc ...
Material-UI provides some reset styles as you can observe here CssBasline.js mainly box-sizing and body font color and background color
'#global': {
html: {
WebkitFontSmoothing: 'antialiased', // Antialiasing.
MozOsxFontSmoothing: 'grayscale', // Antialiasing.
// Change from `box-sizing: content-box` so that `width`
// is not affected by `padding` or `border`.
boxSizing: 'border-box',
},
'*, *::before, *::after': {
boxSizing: 'inherit',
},
'strong, b': {
fontWeight: 'bolder',
},
body: {
margin: 0, // Remove the margin in all browsers.
color: theme.palette.text.primary,
...theme.typography.body2,
backgroundColor: theme.palette.background.default,
'#media print': {
// Save printer ink.
backgroundColor: theme.palette.common.white,
},
},
The docs say that its a collection of HTML element and attribute style-normalizations. It's based on normalize.js, which is a modern cross-browser CSS reset for your HTML elements that preserves some of the defaults.
Basically, it resets your CSS to a consistent baseline. That way, you can restyle your HTML doc so that you know you can expect all of the elements to look the same across all browsers.
What normalize.js does, from the readme linked above:
Preserves useful defaults, unlike many CSS resets.
Normalizes styles for a wide range of elements. Corrects bugs and common browser
inconsistencies.
Improves usability with subtle modifications.
Explains what code does using detailed comments.
import { createMuiTheme } from "#material-ui/core/styles";
const theme = createMuiTheme({
overrides: {
MuiCssBaseline: {
"#global": {
"*, *::before, *::after": {
boxSizing: "content-box",
},
body: {
backgroundColor: "#fff",
},
},
},
},
});
export default theme;
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { BrowserRouter } from "react-router-dom";
import { MuiThemeProvider } from "#material-ui/core/styles";
import theme from "./Theme/Theme";
ReactDOM.render(
<MuiThemeProvider theme={theme}>
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
</MuiThemeProvider>,
document.getElementById("root")
);
serviceWorker.unregister();
Basically, The MUI provides MuiCssBaseline that overrides some of our CSS styles. But MUI
provides the flexibility to override its default style. Here is what I have implemented
1: Create a theme.js and import createMuiTheme. Then override the styles of MuiBaseline based on your requirements and export the theme.js.
2.If you want the overridden style all over your application then import theme.js, MuiThemeProvider from material-ui/core/styles into your index.js, MuiThemeProvider takes the theme as an argument and then applies the style to its children components.
Related to - but I can't seem to find an answer anywhere.
You can find code for CssBaseLine in the repository for the Material-UI library on Github by following link.
By putting at top of your component is used for providing a lot of default styling for your material UI applications so that you don't have to worry about basic styles of your component

How can I expose my material-ui theme to the console like material-ui site?

I am working on a React project and have decided to use material-ui for the styling, but am also having to learn how to use it in the process. I keep running into bumps with the theme-ing, have been reading the material-ui documentation and other resources online, but am still having trouble getting a grasp on it. I thought being able to see my theme in the Chrome inspector/dev tools would be helpful as material-ui has done on their site, but I don't know how to do it. How can I expose my theme to the console?
material-ui exposes a global theme variable on all the pages
Since you don't seem to have created a custom theme, your theme object should be exactly the same as on the website!
If you really want to see yours in the console try to console log it when declaring your styles on a component like this!
const styles = theme => console.log(theme) || ({
bold: {
fontWeight: 'bold',
}
});
And then when exporting your component use
withStyles(styles)(YourComponentHere);
I'd suggest stashing theme on window once in your <App /> component:
function App() {
React.useEffect(() => {
window.theme = theme;
console.info({ theme });
}, [theme]);
return (
<ThemeProvider theme={theme}>
{/* ... */}
</ThemeProvider>
);
}
export default App;

MUI dark theme isn't applied to the background

I have my react application where I want to apply MUI darkBaseTheme. Without it, part of my app looks like this:
After I wrap all the html stuff in my render() with:
<MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
</MuiThemeProvider>
Having those imports:
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; // add
import RaisedButton from 'material-ui/RaisedButton'; // add
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme';
It looks like this:
So it changed RaisedButtons. I know it shouldn't change html ones. But why didn't it change the background to dark? Is there a way to do this, or do I have to do it manually without MUI?
You need to include the <CssBaseline /> component at the root of your app as this is what deals with changing the background colour on the body.
Docs
I had a similar issue. The body background was not changing when I switched to dark mode.
Solution:
Move your CssBaseline inside MuiThemeProvider. Otherwise the body background won't change when you use type dark in your theme.
<MuiThemeProvider theme={theme}>
<CssBaseline />
<App />
</MuiThemeProvider>
MUI v5 Update
You can change the background to a dark color by setting the mode property to dark, and include the CssBaseline which sets the backgroundColor of the body element:
const theme = createTheme({
palette: {
mode: 'dark',
},
});
<ThemeProvider theme={theme}>
<CssBaseline />
<Content />
</ThemeProvider>
If you want to use a custom color for the background:
const theme = createTheme({
palette: {
background: {
default: 'gray',
},
},
});

Resources