Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load SCSS file dynamically on button click

different CSS files

as you can see I have a scss file loaded for the entire project and I'd like to know if it is possible to change what scss file is loaded on the click of the button. keep in mind this scss file applies on the root component but I'm going to place the button on a component that's it's grand-child.

I've tried a couple things along things but the problem is apparently there's no way to attribute a scss file other than by an import ( This is in /Components/App.jsx ) :

import '../scss/app.scss';
//import '../scss/darcula.scss'; for dark theme.

and if I uncomment the above the imported scss is darcula but I have no way to dynamically change the import set that I know of.

an acceptable solution would be a triggered seperate import that happens within the child which does not entirely replace the other file but instead only supersedes each redefined style allowing me to only change the collors to obtain this "night mode" button that I want.

I don't understand why requires can't be isolated inside ifs Even if I do this :

turnLightsOnOff() {
    if (this.state.theme) {
        require('../../../scss/app.scss');
        this.setState({
            theme: false,
        });
    } else {
        //require('../../../scss/darcula.scss');
        this.setState({
            theme: true,
        });
    }
}

app.css is loaded even thought the condition for that if is not yet met

and if I uncomment the other line both scss are loaded one one top of another.

like image 857
tatsu Avatar asked Sep 06 '17 10:09

tatsu


2 Answers

SCSS needs to be compiled at build time. Browsers do not have the ability to process SASS. In adition the require() method is a webpack method run at buildtime and not dynamically in the browser. What you could do is create splits with webpack utilizing something like extract-css-chunks plugin

like image 182
simsom Avatar answered Sep 21 '22 12:09

simsom


You can check this question for detail on theme managing. What I'm suggesting is the simpler solution (in my opinion)

Rather than seperating files with different styles like this;

/* main.css */
#box {
    position: absolute;
    top: 50px;
    left: 50px;
    width: 200px;
    height: 200px;
}

/* theme1.css */
#box {
    backround-color: red;
}

/* theme2.css */
#box {
    background-color: maroon
}

Setting them in a single file like this;

#box {
    position: absolute;
    top: 50px;
    left: 50px;
    width: 200px;
    height: 200px;
}

div.theme1 #box {
    backround-color: red;
}

div.theme2 #box {
    background-color: maroon
}

I know this is a css solution rather than scss but the logic is pretty much the same.

You can set the desired theme className on a higher level component and effect whole app.

class App extends React.Component {
    render() {
        return (
            <div className={this.props.theme}>
                <MainApp />
            </div>
        )
    }
}

Update

You can do conditional require according to this answer.

class Main extends Component {
    componentWillMount() {
         if(this.props.language === 'ar') {
            require('arabic.css');
         } else {
            require('english.css');
         }
    }
}
like image 42
bennygenel Avatar answered Sep 18 '22 12:09

bennygenel