theme system

Hey, what would ya'll recommend as a good method to go about creating themes for a site? I had the idea of applying variables to html and having a data attribute toggle along with prefers-color-scheme (or lightdark()) e.g.
:root {
--bg-light: ...;
--bg-dark: ...;
}

@media (prefers-color-scheme: light) {
html {
--button-bg: var(--bg-light)
}
}

@media (prefers-color-scheme: dark) {
html {
--button-bg: var(--bg-dark)
}
}

html[data-light] {
--button-bg: var(--bg-light);
}

html[data-dark] {
--button-bg: var(--bg-dark);
}
:root {
--bg-light: ...;
--bg-dark: ...;
}

@media (prefers-color-scheme: light) {
html {
--button-bg: var(--bg-light)
}
}

@media (prefers-color-scheme: dark) {
html {
--button-bg: var(--bg-dark)
}
}

html[data-light] {
--button-bg: var(--bg-light);
}

html[data-dark] {
--button-bg: var(--bg-dark);
}
I'm not sure if this is a good maintainable way of doing something like this though. I'd appreciate any insight. Thanks in advance
22 Replies
b1mind
b1mindā€¢3w ago
good way to go about it imo You could make the tokens a bit better maybe and not so specific.
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
i would do something better your implementation has a possible bug, where stuff is a mix of dark and light
b1mind
b1mindā€¢3w ago
I typically override the root šŸ¤”
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
what you can do is something like this:
:root {
--theme: white;
@media (prefers-color-scheme: dark) {
--theme: black;
}

&[data-theme="dark"] {
--theme: black;
}
}

@container style(--theme: black) {
body, ::backdrop {
--bg: black;
}
}

@container style(--theme: white) {
body, ::backdrop {
--bg: #eee;
}
}

body {
background-color: var(--bg);
}
:root {
--theme: white;
@media (prefers-color-scheme: dark) {
--theme: black;
}

&[data-theme="dark"] {
--theme: black;
}
}

@container style(--theme: black) {
body, ::backdrop {
--bg: black;
}
}

@container style(--theme: white) {
body, ::backdrop {
--bg: #eee;
}
}

body {
background-color: var(--bg);
}
or something like that also, you only define the colors in 1 place i hope it works, because i didnt try it šŸ¤” doesnt seem to work, so, i will explore there, updated it here's a more refined example:
:root {
--theme: white;

@media (prefers-color-scheme: dark) {
--theme: black;
}

&[data-theme="dark"] {
--theme: black;
}

&[data-theme="light"] {
--theme: white;
}
}


body, ::backdrop {
@container style(--theme: white) {
--bg: #eee;
--color: #333;
}

@container style(--theme: black) {
--bg: black;
--color: white;
}
}


body {
color: var(--color);
background-color: var(--bg);
}
:root {
--theme: white;

@media (prefers-color-scheme: dark) {
--theme: black;
}

&[data-theme="dark"] {
--theme: black;
}

&[data-theme="light"] {
--theme: white;
}
}


body, ::backdrop {
@container style(--theme: white) {
--bg: #eee;
--color: #333;
}

@container style(--theme: black) {
--bg: black;
--color: white;
}
}


body {
color: var(--color);
background-color: var(--bg);
}
snxxwyy
snxxwyyOPā€¢3w ago
Because of the prefers color scheme? Like if someone has prefers color scheme dark and the site is default to the data attribute light it could conflict?
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
yeah, and there's the risk that some stuff is light and other stuff is dark also, you're repeating yourself
snxxwyy
snxxwyyOPā€¢3w ago
How so?
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
@media (prefers-color-scheme: light) {
html {
--button-bg: var(--bg-light)
}
}

html[data-light] {
--button-bg: var(--bg-light);
}
@media (prefers-color-scheme: light) {
html {
--button-bg: var(--bg-light)
}
}

html[data-light] {
--button-bg: var(--bg-light);
}
you're doing the same work twice
snxxwyy
snxxwyyOPā€¢3w ago
oh i see. i was thinking that way because one is the browser preference and the other is a toggle switch
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
this works exactly the same: just don't add the data-theme attribute and you don't repeat yourself and when you add the data attribute, it respects the attribute and it's easier to extend as well by the way, you have to replicate the styles to the ::backdrop element, if you use dialogs or videos ::backdrop is special - it doesn't inherit any properties
snxxwyy
snxxwyyOPā€¢3w ago
oh okay i see. in your solution, what are the positives of the @container style() declarations? couldn't you do this? or is that unecessary repetition?
:root {
--bg: #eee;
--color: #333;

@media (prefers-color-scheme: dark) {
--bg: black;
--color: white;
}

&[data-theme="dark"] {
--bg: black;
--color: white;
}

&[data-theme="light"] {
--bg: #eee;
--color: #333;
}
}
:root {
--bg: #eee;
--color: #333;

@media (prefers-color-scheme: dark) {
--bg: black;
--color: white;
}

&[data-theme="dark"] {
--bg: black;
--color: white;
}

&[data-theme="light"] {
--bg: #eee;
--color: #333;
}
}
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
the positives: you dont repeat yourself by not repeating yourself, you also don't make any mistakes imagine you have 30 variables now, you need to update the same value twice per theme
clevermissfox
clevermissfoxā€¢3w ago
So are you setting the html El as a container-type for this?
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
im just doing this nothing else that's the entire css
clevermissfox
clevermissfoxā€¢3w ago
So if no container is defined, @container refers to the html
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
yes, the body and ::backdrop
Doksuri
Doksuriā€¢3w ago
can you explain theses lines ? @container style(--theme: white) { i don't quite get it... even if i kind of understand what it does
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
it's a container query that checks the value of the custom property, and compares to the value given think of this as an if that checks if --theme is equal to white
Doksuri
Doksuriā€¢3w ago
i can't find the mdn doc of style() function -_- https://caniuse.com/css-container-queries-style is this it ?
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
yes it is you can also just google "query containers with style" and it should show the mdn page
į¼”ĻĻ‰Ļ‚
į¼”ĻĻ‰Ļ‚ā€¢3w ago
you're welcome
Want results from more Discord servers?
Add your server