4

I have a React 16 app and would like to allow the user to change the theme for the entire app (including all Routes) by pressing a button.

So for example, I could have two themes in SCSS:

.theme-1 {
    background-color: $bg-color-1;
    color: $color-1;
}
.theme-2 {
    background-color: $bg-color-2;
    color: $color-2;
}

Then I would have a button as follows:

<Button onClick={ this.changeTheme() }

Can this be done? Specifically, I want to figure out these two parts:

  1. How to set the theme on all components that need to use the various background-color and color.
  2. The logic of the changeTheme() function. How exactly it would go about triggering a re-render on all affected components.

Thanks!

Alex Verzea
  • 421
  • 1
  • 11
  • 30

1 Answers1

6

The best way to do it is by using css variables.

You need to specify your theme using css variables and on some user action add additional css in your site.

  1. Create single theme like you have mentioned above

     --color: blue;
     --bg-color: red;
     .theme {
         background-color: var(--bg-color);
         color: (--color);
     }
    
  2. Add additional styles right inside your component

    {this.state.useTheme && <style type="text/css">
        :root {
            --color: blue;
            --bg-color: red;
        }   
    </style>}
    
  3. Change flag on user click

    <div onClick={this.setState({useTheme: true})}> Apply theme </div>
    

or another variant

  1. Create additional theme.css file where you specify different variables

    --bg-color: yellow;
    --color: green;
    
  2. attach it on some user action. Code source from here

    { var head = document.getElementsByTagName('head')[0]; var link = document.createElement('link'); link.id = cssId; link.rel = 'stylesheet'; link.type = 'text/css'; link.href = 'http://your-website.com/path-to-css-file/theme.css'; link.media = 'all'; head.appendChild(link); }}> Change theme

By doing like that you will avoid a lot of code duplication. Because you don't need to create multiple themes. You only need to add small additional css on change, so you can create a lot of themes or even let user to customize them.

Arseniy-II
  • 8,323
  • 5
  • 24
  • 49
  • css variable are not supported by all the browsers, in that case how will it fallback – atul Jan 04 '20 at 19:51
  • @atul almost nothing is supported by **all** browsers. [css variables are supported by all modern browsers](https://caniuse.com/#search=css%20var). The only reasonable concern is IE11 in that case. [But IE11 is less than 1% of total users](https://www.w3schools.com/browsers/browsers_explorer.asp). [And most likely supporting those users isn't wise.](https://medium.com/@burger.neal/the-end-of-life-of-internet-explorer-11-12736f9ff75f). – Arseniy-II Jan 05 '20 at 09:37