I'm currently working with a team developing a bunch of web components, supposed to be the basis for a current and also upcoming web applications developed in the customer's company.
I want these components to support color themeing; the first use-case for this being supporting a dark mode.
Current approach
I have defined the customer's corporate design colors in a file
colorpalette.css(the colors are just an example)::root { --color-blue: #004994; --color-light-blue: #0095db; --color-light-green: #afca06; --color-light-grey: #9c9c9c; --color-green: #51ae31; --color-grey: #555555; --color-orange: #f39200; --color-red: #d40f14; --color-turquoise: #008c8e; --color-violet: #b80d78; --color-yellow: #ffcc00; --color-white: #ffffff; --color-black: #000000; }I'm making sure all other files using or defining colors only use colors from this file. This leads to a file
colors.csswhere I start defining different colors per theme:@import "./colorpalette.css"; :root { --bg-color-button: var(--color-light-grey); --text-color-button: var(--color-black); --border-color-button: var(--color-grey); } :root[data-theme=dark] { --bg-color-button: var(--color-grey); --text-color-button: var(--color-white); --border-color-button: var(--color-light-grey); }
So far, I'm satisfied with this approach.
Problem
Now I'm starting to add different semantic versions of these buttons: .btn-danger, .btn-success, etc. which are supposed to use color as a means of transporting these semantics.
Possible solutions - two different alternatives
And here is where I'm uncertain as of which way to pursue to achieve this, as I see 2 alternatives:
Create new variables for these semantics, carrying the semantic in their name:
:root { --bg-color-button-success: var(--color-light-green); --text-color-button-success: var(--color-black); --border-color-button-success: var(--color-green); }and use these in the button style definitions:
.btn { background-color: var(--bg-color-button); color: var(--text-color-button); border-color: var(--border-color-button); } .btn.btn-success { background-color: var(--bg-color-button-success); color: var(--text-color-button-success); border-color: var(--border-color-button-sucess); }- Pros
- You can re-theme the whole application by modifying only two files.
- Cons
- This approach obviously results in a myriad of variables, as we need to define a separate variable for each place where we need to apply a different color.
- If you later want to introduce additional button variations, you'd have to edit both
colors.cssandbutton.css.
- Pros
The other approach could be redefining the existing variables in the specified context:
.btn { background-color: var(--bg-color-button); color: var(--text-color-button); border-color: var(--border-color-button); } .btn.btn-success { --bg-color-button: var(--color-light-green); --text-color-button: var(--color-black); --border-color-button: var(--color-green); }- Pros
- alot less variables.
- Variables only get redefined in places where they're actually used.
- Defining new button variants is easier than in the other approach as you only need to edit
button.css.
- Cons
- To retheme the component library, you will probably have to touch every single component's css file in addition to
colorpalette.cssandcolors.css.
- To retheme the component library, you will probably have to touch every single component's css file in addition to
- Pros
I've tried to sum up the pros and cons I see for both approaches.
Question
Which would be other reasons to prefer one over the other way?
Hint
Please consider the following before eventually voting to close:
I know many might see this question as off-topic because it attracts opinionated answers, but I'm sure this question has alot of practical relevance for many developers as css custom properties have only recently become the de-facto standard, which usually results in best practices emerging only slowly. So opinionated answers along with reasons for these opinions are exactly what I'm asking here intentionally.
This is also in no way a duplicate of Best Practices - CSS Theming because that question is from 2010 where css custom properties didn't exist.