Material UI: dynamically control createMuiTheme background properties with reported window dimensions

Viewed 77

I'm looking for a way to dynamically set backgroundSize and backgroundPosition properties in createMuitheme method, based on reported window dimensions from a hook, used in a page container where ThemeProvider and CssBaseline are invoked. I'm using next 10.2.0, which depends on react{-dom} 17.0.2 (any solution should be mostly compatible with either one).

Alternatively, if someone has a solution using styled-components ^5, I'd be happy to adopt that instead.

I have window.{innerHeight,innerWidth} logging properly to console upon window resize. The part where I get tripped up, is once I have the dimensions, how would I feed them back into the createMuiTheme object (?)

Would I have to alter overrides.MuiCssBaseline.'@global'.body using makeStyles in a child function (?) I imagine there's probably more than one way to approach this - any ideas much appreciated.

globalTheme.js:

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

const theme = createMuiTheme({
  overrides: {
    MuiCssBaseline: {
      '@global': {
        body: {
          // border: '2px solid blue',
          backgroundImage: `url("/background-image.jpg")`,
          backgroundAttachment: `fill`,
          backgroundSize: `cover`,
          backgroundPosition: `0 0`,
          backgroundRepeat: `no`,
        },
      },
    },
  },
});

export default theme;

useDimensions.js hook:

import { useState, useEffect } from 'react';

const useDimensions = () => {

  const [windowSize, setWindowSize] = useState({
    width: undefined,
    height: undefined,
  });
  useEffect(() => {
    function handleResize() {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []); 

  return windowSize;

};

export default useDimensions;

PageContainer.jsx wrapper:

import { Fragment } from 'react';
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import theme from 'styles/globalTheme';
import useDimensions from 'hooks/useDimensions';

const PageContainer = ({ children }) => {
  const { width, height } = useDimensions();
  return (
    <Fragment>
      {console.log(width, height)}
      <ThemeProvider theme={theme}>
        <CssBaseline />
        {children}
      </ThemeProvider>
    </Fragment>
  );
}

export default PageContainer;

console.log(height, width) e.g.:

853 937  # reports on resize of window
0 Answers
Related