Customizing Material UI themes with CSS variables is a powerful feature of the createMui

In an attempt to create a Material UI theme using existing colors defined as CSS variables in my-palette.scss, the following code is utilized:

:root {
  --primary-color: '#FF0000';
  ...
}

The goal is to incorporate these colors like so:

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

export const muiTheme = createMuiTheme({
  palette: {
    primary: {
      main: 'var(--primary-color)',
    },
  },
});

This command triggers an error message:

Error: Material-UI does not support the color format var(--primary-color). Supported formats include: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla().

A Github thread suggests that this feature is currently unsupported: Support CSS variables as theme option.

Is there a workaround available to utilize var(--primary-color) as the primary color in a Material UI createMuiTheme?

The objective is to easily override default Material UI component colors with custom ones such as primary, secondary, etc.

<Radio color="primary" />

Alternative attempts have included extracting colors from the palette like this:

const cssVariables = {
  primaryColor: getComputedStyle(document.documentElement).getPropertyValue('var(--primary-color)'),
};

However, utilizing cssVariables.primaryColor has been ineffective and non-intuitive.

The final proposed solution involves manually recreating the palette as a standard object and using it directly, but this method seems cumbersome for maintenance purposes.

Answer №1

The MUI development team is actively working on incorporating CSS variables into their framework. Keep tabs on the progress here and delve into the specifics here. For official documentation, visit this link.

Latest update as of 21st December 2022

CSS variables have now been implemented by MUI as part of an experimental API. Refer to the documentation here for more details.

Answer №2

One approach shared by NearHuscarl effectively accomplishes the task, although a slight flicker is present due to the palette change. To eliminate this issue, implementing lazy initialization within the useState function can be beneficial.

const cssVar = (name: string) =>
  getComputedStyle(document.documentElement).getPropertyValue(name).trim();

const App: React.FC = () => {
  const [theme] = useState(() =>
    createTheme({
      palette: {
        primary: {
          main: cssVar("--color-primary"),
          light: cssVar("--color-primary-light"),
          dark: cssVar("--color-primary-dark"),
          bg: cssVar("--color-primary-bg"),
          contrastText: cssVar("--color-primary-contrast-text"),
        },
      },
    })
  );

  return (
    <ThemeProvider theme={theme}>
      <YourApp />
    </ThemeProvider>
  );
};

Answer №3

The workaround in question is effective, although it seems likely that getComputedStyle() is being called within the module scope before the stylesheets are fully initialized.

One potential solution would be to place this code snippet inside the render method as shown below.

const [theme, setTheme] = React.useState(null);

React.useLayoutEffect(() => {
  const color = getComputedStyle(document.documentElement)
    .getPropertyValue("--your-css-color")
    .trim(); // leading whitespace may be present in the result.

  setTheme(
    createMuiTheme({
      palette: {
        primary: {
          main: color
        }
      }
    })
  );
}, []);

Live Demo

https://codesandbox.io/s/63916278css-variables-in-material-ui-createmuitheme-jmofo?file=/src/App.js

Answer №4

Utilizing color options from your theme settings can be a more efficient approach. By doing so, you have the ability to specify Material UI colors as CSS variables.

import React, { useEffect } from 'react'
import { createTheme, ThemeProvider } from '@mui/material/styles'

import { indigo, amber } from '@mui/material/colors'
const themeOptions = createTheme({
  palette: {
    primary: { main: indigo[500] },
    secondary: { main: amber[600] },
    background: { default: '#F3F6F9' },
  },
})
const colorKeys = ['background', 'common', 'error', 'grey', 'info', 'primary', 'secondary', 'success', 'text', 'warning']
const r = document.querySelector(':root')
const AppThemeProvider = ({ children }) => {
  useEffect(() => {
    colorKeys.forEach((color) => {
      const themeColorObj = themeOptions.palette[color]
      for (const key in themeColorObj) {
        if (Object.hasOwnProperty.call(themeColorObj, key)) {
          const colorVal = themeColorObj[key]
          r.style.setProperty(`--color-${color}-${key}`, colorVal)
        }
      }
    })
  }, [])
  return <ThemeProvider theme={themeOptions}>{children}</ThemeProvider>
}
export default AppThemeProvider

This method allows you to leverage CSS variables like Sass or traditional CSS.

.dx-link-edit {
  color: var(--color-primary-main);}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Utilize Ajax to load PHP content and dynamically refresh a specific div

I have implemented an image uploading system, but now I want to incorporate a feature that allows users to rotate the uploaded images using Ajax. The challenge I'm facing is that if the session variable is lost during a full page update, I need to ens ...

Error: We are facing an issue with new.mongoose.Schema as it is not functioning properly and

I am experiencing an issue with my product.js file. It keeps throwing an error about an unidentified identifier, and whenever I try to fix one problem, another one pops up. I have been struggling to locate the root cause of this error. ...

How do I detect the " * " key in a keyEvent?

if(keyEvent.keyCode == 8){ $scope.erase(); } else if(keyEvent.keyCode === 107){ console.log("+"); $scope.inputToCal('+') } else if(keyEvent.keyCode === 109){ console.log("-"); $scope.inputToCal('-&ap ...

Dealing with Socket.io connection problems on Node.js and Windows 10 platform

Just starting with nodejs and recently set it up on my Windows10 machine. I decided to create a folder within Nodejs and included a server.js file. Next step was installing socket.io using the command "npm install socket.io". Here's a snippet of what ...

Exploring the GET request in Meteor JS

When using Meteor JS, I have a get function set up like this: localhost:3000/profile?user=rishav I am now trying to access the value of user in a Meteor JS template. When dealing with post data, we can use event.target.blah.value; where blah is the id. H ...

Arranging arrangements in javascript

I am dealing with objects that contain the fields id and position. const items = [{id: 11, position: 1}, {id: 12, position: 2}, {id: 13, position: 3}, {id: 14, position: 4}, {id: 15, position: 5}, {id: 16, position: 6}]; These objects represent folders st ...

showing a loading spinner while sending an ajax request, patiently awaiting the response, and preventing any further interactions on the page

On my page, I am utilizing multiple ajax calls to load specific parts of the response. However, I need to display a spinner on the section where the ajax call is being made to indicate that content is loading. Is there a way to create a universal method th ...

What is the best way to retrieve the offsetHeight of a Component Element using Vue.js?

I am currently working on a Vue.js component and successfully inserting it into the DOM. My goal is to find out its rendered height once it's in the DOM, specifically its offsetHeight. However, I seem to be missing something obvious as I can't fi ...

Unable to modify styles by using classes in material-ui

I am really struggling to grasp how to customize the styles for a one-time use of TextField The documentation is not connecting with me at all <FormControl> <InputLabel htmlFor="mobile-number-input" > Mobile Number </InputLab ...

The ArrowHelper in THREE.js seems to be ignoring the natural rotation provided by Euler angles

Can someone help me with setting intrinsic rotations to a THREE.ArrowHelper in THREE.js? I'm trying to work with Tait-Bryan euler angles for 3D rotations. In the snippet below, I define a unit vector for the x-axis as THREE.Vector3(1, 0, 0). Then, I ...

Acquiring exclusive files from Laravel 8 storage directory using JavaScript

I find myself in a specific situation: Working with a Laravel 8 application. My users upload STL files, which are stored in the storage/app/users/{userid} directory. These STL files are private and not accessible to everyone as they are not located in the ...

Troubleshooting problems with React Hook Form Controller

Hey there, I'm currently working on creating a form using react-hook-form and material-ui. I want to avoid writing Controller every time for all TextFields, so I decided to declare it in another file and call it in my form. However, I'm facing is ...

I am interested in creating a text box that has the ability to gather user input and connect it to a search

I have been attempting to develop a text box that can collect answers and link them with the search URL. However, I am encountering issues where even though I can input text into the textbox, it is not being recognized by the script. The error message sh ...

Having trouble with the JQuery scrollTop animation? Getting the error message "Cannot read property 'top' of undefined"?

I am having trouble with my jquery animation scrollTop function. Whenever I click on <a>, it takes me to the anchor without any animation. Can someone please provide a solution for this issue? Upon running the webpage, I encountered an error message ...

What is the best method for incorporating a Vue 2 component into an HTML single file that relies on Vue 3's UMD build?

Exploring the utilization of (an intricate multi-select component with nested options) in a standalone Vue 3 single local HTML file, without relying on the Vue CLI for this specific task. When using the UMD build for Vue 2, it functions as outlined below ...

jQuery: event not firing for dynamically loaded elements via AJAX

In my jQuery/HTML5 front-end setup (with backend-generated code omitted), I am currently using version 1.8.3 of jQuery with no version conflicts. The front-end calls the following functions: detailAjaxCall("\/client\/orders\/detailsLoad&bso ...

It is not possible to use Date.now within passport.js

When creating a user via Facebook on my Node.js website using passport, I want to assign the register date. In my Mongoose Schema, I can use the following for the local provider: regisDate: { type: Date, default: Date.now }, However, when it co ...

Is it possible for node.js to execute promises without needing to await their fulfillment?

When I visit the Discord tag, I enjoy solving questions that come my way. While I am quite proficient in Python, my skills in Javascript are just about average. However, I do try my hand at it from time to time. The Discord.py library consists of several ...

Mastering jQuery ajax in Google Chrome Extensions

I have developed a script to fetch data from an external server using JSONP request in jQuery. Please take a look at the code snippet below: $("#submit").click(function() { var state = $("#state").val(); var city = $("#city").val(); $.ajax({ ...

Exploring ways to display featured posts within specific category sections

I have 2 featured posts in 1 div id, one with a big class and the other with a small class. I want the big featured div to display posts based on categories. The code for the big featured post is shown below: <div class="main_feat"> ...