I want to allow users to select themes on my website, which they will do through a dropdown this. I am currently having trouble figuring out how to support this feature though, without writing dumb code.
I currently use css-modules along with postcss to make my life easier. Webpack is used to bundle everything together. I utilize hot reloading during development, during which I use the style-loader instead.
The full configuration looks like this
{
test: /\.css$/,
loader: !isDev
? ExtractTextPlugin.extract('style-loader', 'css-loader?sourcemap&minimize&modules&importLoaders=1&localIdentName=[name]-[local]-[hash:base64:5]!postcss-loader')
: 'style-loader!css-loader?sourcemap&minimize&modules&importLoaders=1&localIdentName=[name]-[local]-[hash:base64:5]!postcss-loader'
},
Solution 1
Place a classname on the body tag to determine what theme is loaded. This is then used to select the correct theme from inside each components css. This is quite tedious and something I'd like to avoid, but it would look something like this:
.myComponent {
margin: 10px;
width: 100px;
}
:global(.theme1) {
.myComponent {
background: $theme1_myComponent_background;
}
}
:global(.theme2) {
.myComponent {
background: $theme2_myComponent_background;
}
}
This is quickly going to turn into something hard to extend and unmaintainable which is why I would like to avoid it.
Solution 2
Generate pre-themed static bundles for the css. When the user requests /main.css
, a handler on the server determines which theme to send (perhaps query string) and sends them theme1-main.css
or theme2-main.css
or something along those lines. The problem there is I don't know how to support the dev environment.
The good thing about this is that my css files don't need any extra and hard to maintain logic:
.myComponent {
margin: 10px;
width: 100px;
background: $myComponent_background;
}
Solution 3
Use native css variables. These can then be updated during runtime which would reflect the already loaded css and work gracefully across both production and development environments. My components would also look like (or similar to) solution 2. The problem here is that they are not very widely supported natively, and I'm unsure if there are any polyfills worth looking into that will do this type of thing for me.
All in all, these are my thoughts. I have not arrived at any definitive conclusion yet and would appreciate all feedback on how I can solve this problem. Perhaps I'm thinking about it all wrong and there is a much better way of doing what I want done.
Thanks in advance!
One possible approach could be as follow
style-loader
because it inserts css automatically, but do it manually when we need and what we need.for example:
(we need
raw-loader
here)for example:
just put another style to
href
:or let's do same via React:
it'll work if you set the
raw-loader
to handle css file in webpack.configHere is a solution using SASS. It's basically your solution 1 but easier to write and maintain. It seams that you're not using SASS but since it's the best solution I could find for my personal use, I thought it worth sharing...
Here is the SCSS code (CodePen here):
It requires this to work:
Resulting CSS:
This is heavily inspired by: