Adding CSS background image to Material UI theme - css

In material UI, the theme can be adjusted and/or overridden using the createMuiTheme function. This is the full file in which I am doing so:
import { createMuiTheme } from '#material-ui/core/styles';
import purple from '#material-ui/core/colors/purple';
import green from '#material-ui/core/colors/green';
//import wood from './static/wood.png';
const theme = createMuiTheme({
palette: {
primary: {
main: purple[500],
},
secondary: {
main: green[500],
},
},
overrides: {
MuiCssBaseline: {
'#global': {
body: {
border: '2px solid blue',
backgroundImage: 'url("/static/wood.png")',
},
},
},
},
});
export default theme;
The global styling applied to the body is confirmed working- I can see the blue border. However, nothing I try will get the background image to work.
Normally, I would uncomment the import statement at the top: import wood from './static/wood.png'; and then change the CSS line to:
backgroundImage: `url(${wood}),`
However, the import statement alone is causing a crash:
TypeError: Object(...) is not a function. It seems that there is something special about customizing a material ui theme that doesn't allow static assets to be imported in the same file.
When I instead attempt to use a url for the image (shown above), it is always a 404 error. My file structure places the image in src > static > wood.png, but I get:
http://localhost:3000/static/wood.png 404 (not found).
I've tried dozens of possible path variations, but none have worked, and all my efforts to research the proper path just indicate that I'm already using the correct path.
Is it only possible to add a background image to the body using Material UI theme customization when the background image is hosted on a separate server?
The only working examples I've found do it that way (like this one: https://codesandbox.io/s/v30yq681ql), but it seems like there must be a way to use an image stored locally.
Or if the problem really is that my relative path is incorrect, what can I do to find out what the correct one would actually be?
If there is a better way to add a background image to a page with Material UI that would work too, though I haven't seen any other way to do it than a global override of the body tag.

If you put your image within the src folder instead of static, e.g.
src/components/wood.png
Reinstate your import like:
import wood from './components/wood.png';
and then put the backgroundImage to:
backgroundImage: `url(${wood})`,
that should work. The same configuration (with different filename, but in the same location) works for me.

Related

How to give path/url for background image in tailwind?

I'm using Tailwind in my React Project. I want to add a background image in a div but it shows the following error:
Module not found: Error: Can't resolve '../../icons/blog-hero-1.png' in 'C:\Users\DELL\frontend-development\aidhumanity-practice-2\src'
I'm adding tailwind class
bg-[url('../../icons/blog-hero-1.png')]
for adding background image and url is relative to the current file and also it's working when added normal image through:
import Hero from "../../icons/blog-hero-1.png"
<div>
<img src={Hero} className="h-full rounded-3xl"></img>
</div>
Can anyone guide how to give the correct url?
Note: I've added a codesandbox example here as well for better demonstration in which I've tried to import background image in "Homepage.js" but it's not working.
https://codesandbox.io/s/background-image-wl9104?file=/src/components/Homepage.js
Well you can achieve the same result with the below approach as well:
In your tailwind.config.js file:
module.exports = {
theme: {
extend: {
backgroundImage: {
'hero': "url('../../icons/blog-hero-1.png')"
}
},
},
plugins: [],
}
You can simply mention bg-hero in you class to implement.

Tailwind colors from API call

I've had a look around and there doesn't really seem to be an answer to this.
I have an CMS API that provides things like branding colors etc... for a React app that can "reskin" it's self using a mix of colors and images etc...
I'm working on a V2 of this app and want to switch from sass/scss to tailwind. With sass and scss we kind of just overwrote colors with CSS in JS and it worked pretty well.
In tailwind if you want to add a custom color pallet you need to create a config file etc... This will not work for my indented use as the colors will be changing on the fly.
Imagine a component:
import { FC } from 'react';
const MyComponent: FC = () => {
return <div className='bg-blue-500'></div>;
};
This works great however if I want to change the color as a one off I could use a classname like bg-[#f1f1f1] and this also works great!
However the issue seems to come if I get React to put this color as a template string, like so:
import { FC } from 'react';
import { useBranding } from '../some_path';
const MyComponent: FC = () => {
const [branding] = useBranding(); // custom hook, all you need to know is it has colours that it spits out colors
return <div className={`bg-[${branding.colours.primary}]`}></div>;
};
At this point if I inspect the page I can see the color code goes in and should work. However I'm assuming that Tailwind has some preprocessing that get skipped if I do this?
Any ideas on how I can use colors in this way with tailwind?
Tailwind doesn't detect classes after build.
I might be wrong as you're not showing how your hook works, but I'd say you can use style tag instead:
import { FC } from 'react';
import { useBranding } from '../some_path';
const MyComponent: FC = () => {
const [branding] = useBranding(); // custom hook, all you need to know is it has colours that it spits out colors
return <div style={{backgroundColor: branding.colours.primary}}></div>;
};

Material-UI - why different css is shown on prod environment then development env

I use material UI (verison: ^4.12.3) Select, with custom input.
For some reason the prod env Select input has a black background and :before element with white background.
I don't know from where it comes from.
this is image of the prod:
this is image of the dev Select:
when comparing the 2 css & html of the envs Select element, it's is shown that there is a ::before element added in prod that is not presented in dev
also, the background color is different. in prod there is another class added to the InputBase element, which doesn't exist in dev. this class adds a background-color black:
Edit 1
it seems like MUI inject <style>. in the prod html i see the background-color: black and the ::before. ill try adding the index solution, but my problem is not precedence (the style that i do use override the injected style). also, it wont help the ::before element. how to disable the injected styles ? or work around it ?
the injected bad css:
Please refer to this question. As answered by user Mordechai.
It seems like webpack could mess with MUI's rules on JSS precedence... This could be solved by adding an index of one to MUI's methods.
//Hook
const useStyles = makeStyles({
// your styles here
}, {index: 1})
// HOC
MyComponent = withStyles({
// your styles here
}, {index: 1})(MyComponent)
adding <StylesProvider /> wrapper to the app fixed it. we use micro-frontend infrastructure. and one of the frontends app also had makeStyles. this is causing classNames conflicts in MUI.
in the root component <App/>:
import {
StylesProvider,
createGenerateClassName
} from '#material-ui/core/styles';
const generateClassName = createGenerateClassName({
seed: 'app1'
});
const App = () => {
return (
<StylesProvider generateClassName={generateClassName}>
<OtherAppComponents />
</StylesProvider>
)
}
if you have more then 2 add a provider and a generator to each, with different seed

CSS className isn't making any changes to Reactjs

I'm currently working with rails and reactjs. I'm having difficulties using css in my reactjs files. It seems like every time i try to use it, no change is being applied at all. In my App.jsx file I have this:
import React from "react";
import styles from "./styles.css";
export default class Register extends React.Component {
render() {
return (
<div className={styles.container}>
<h1> this text should appear to the right </h1>
</div>
);
}
}
And in my styles.css file I have this:
.container {
width:40%;
text-align:right;
}
For the record I am using webpack. Can anyone help me understand why the css isn't having any effect on my jsx components. I've looked all over for help but was unable to put the pieces together.
If it matters, this is how my "config/webpack/development.js" file looks like:
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()
It depends on the webpack loader settings. If you are using css-loader as configured in react-scripts (as of 1.1.5), then the classNames are loaded using {modules: false} option, i.e. global styles, which can be referenced as strings in JSX code:
import "./styles.css";
... className="container" ...
Or you can load local styles using following CSS-file syntax:
:local .container {...
Or edit your webpack.config.js appropriately (see https://github.com/webpack-contrib/css-loader#scope for the official documentation of various options).
seems like you didn't enable an option { modules: true } for css-loader in webpack config
take a look
webpack-contrib/sass-loader#206
https://github.com/webpack-contrib/css-loader#options
Taken from: https://github.com/facebook/create-react-app/issues/1350

Theme customization lost when rendering to string on client

I'm using material-ui-next and have customized the theme to use my color styles and a custom font. eg. Typography subheading
I'm now attempting to render a component to string for use in a google maps info window. The default material-ui theme is available in the callback styles object passed to withStyles, but none of my customizations are available on the theme argument in the styles callback nor are they applied. The rendered string renders otherwise correctly (albeit w/o events which I sorta expected).
More concisely, when rendering normally, customizations apply. When rendering to string, they do not.
A simple example would be a component that runs withStyles correctly, but return the div instead of the target component ala:
let output = ReactDOMServer.renderToString(component);
return <div dangerouslySetInnerHTML={{__html: output}} />
Any tips how I can get my theme customizations to be passed into the withStyles callback theme argument?
The solution was to make a parent component that renders the target component as a child of the ThemeProvider. There are still no event handlers (as expected), but the theme customizations apply.
Here's the solution:
MyThemeProvider.js (component can also easily be reused for SSR)
export default function MyThemeProvider({children}) {
const muiTheme = createMuiTheme({
typography: {
fontFamily: '"Bryant", "Helvetica", "Arial", sans-serif',
},
palette: {
primary: customBluePalette,
},
// ...
});
return (<MuiThemeProvider theme={muiTheme}>{ children }</MuiThemeProvider>);
}
MapInfoWindowContent.js (here, this only really exists to wrap VenueRenderer with our theme provider)
import MyThemeProvider from '../MyThemeProvider';
import VenueRenderer from '../VenueRenderer';
export default function MapInfoWindowContent({resource}) {
return (<MyThemeProvider><VenueRenderer resource={resource} /></MyThemeProvider>);
}
VenueRenderer (the styled class - can be used independently of MapInfoWindowContent too)
const styles = (theme) => {
// theme.palette.primary['500'] comes from customBluePalette so the injection worked.
}
// ...
export default withStyles(styles, { withTheme: true })(VenueRenderer);
In some other component that needs the HTML str
import ReactDOMServer from 'react-dom/server'
import MapInfoWindowContent from '../MapInfoWindowContent';
let infoWindowComponent = (<MapInfoWindowContent resource={ ... }/>);
let output = ReactDOMServer.renderToString(infoWindowComponent);
// output will have correctly injected classNames that contain customizations

Resources