Best strategy for light/dark theme using light-dark() function

I'm experimenting with the new light-dark() function and I was looking for ideas on how to better implement the various colours. This is my current implementation:
:root {
/* text */
--l-text-color: #1a1c20;
--d-text-color: #e2e1e1;
/* background */
--l-bg-color: #eeeff1;
--d-bg-color: #1f2023;
/* button border */
--l-btn-border: #0e0f10;
--d-btn-border: #eeecec;

color-scheme: light dark;

--text-color: light-dark(var(--l-text-color), var(--d-text-color));
--bg-color: light-dark(var(--l-bg-color), var(--d-bg-color));
--btn-border-color: light-dark(var(--l-btn-border), var(--d-btn-border));
}
:root {
/* text */
--l-text-color: #1a1c20;
--d-text-color: #e2e1e1;
/* background */
--l-bg-color: #eeeff1;
--d-bg-color: #1f2023;
/* button border */
--l-btn-border: #0e0f10;
--d-btn-border: #eeecec;

color-scheme: light dark;

--text-color: light-dark(var(--l-text-color), var(--d-text-color));
--bg-color: light-dark(var(--l-bg-color), var(--d-bg-color));
--btn-border-color: light-dark(var(--l-btn-border), var(--d-btn-border));
}
My final idea would be, using CSS only, to start from #fff and #000 colors and for the various elements (background, text, borders etc) use a variation of this base color. Is it wrong?
26 Replies
ἔρως
ἔρως3w ago
wrong? doesn't look like it inflexible? it does very much look like it
snxxwyy
snxxwyy3w ago
I use a similar thing for my color scheme toggle, just without light and dark e.g.
:root {
--color-light-primary: #ffffff;
--color-dark-primary: #000000;
--color-primary: var(--color-light-primary);
}

@media (prefers-color-scheme: dark) {
:root {
--color-primary: var(--color-dark-primary);
}
}
:root {
--color-light-primary: #ffffff;
--color-dark-primary: #000000;
--color-primary: var(--color-light-primary);
}

@media (prefers-color-scheme: dark) {
:root {
--color-primary: var(--color-dark-primary);
}
}
Kinda interested in how this type of approach is inflexible. I thought it was since you can re-define the global variables if need be inside of another element?
MC23
MC23OP3w ago
Yeah it seems pretty flexible to me
snxxwyy
snxxwyy3w ago
perhaps it's because you're "fixing" the colors of individual properties in a way e.g. border. You could have a global property as a fallback for a local one instead like so, then it's pretty flexible
:root {
--color-primary: orange;
}

.with-border {
border: 1px solid var(--border-color, var(--color-primary));
}

.card {
--border-color: blue;
}
:root {
--color-primary: orange;
}

.with-border {
border: 1px solid var(--border-color, var(--color-primary));
}

.card {
--border-color: blue;
}
<article class="with-border card">...</article>
<article class="with-border card">...</article>
MC23
MC23OP3w ago
In my case it's for a very simple portfolio page so I don't really have many elements, but yeah that approach would work well
snxxwyy
snxxwyy3w ago
yeah that's fair enough. I'm not sure about the inflexibility then, that's all that comes to mind for me.
ἔρως
ἔρως3w ago
i strongly disagree this doesn't let me choose if i want the light or dark theme you also can't implement anything else besides light or dark what about a purple or pink or green theme?
snxxwyy
snxxwyy3w ago
ohh that's what you mean haha this approach seems more feasible for this then since you can just add different variables right? e.g.
:root {
--color-light-primary: #ffffff;
--color-dark-primary: #000000;
--color-green-primary: limegreen;
--color-primary: var(--color-light-primary);
}

:root[data-theme="green"] {
--color-primary: var(--color-green-primary);
}
:root {
--color-light-primary: #ffffff;
--color-dark-primary: #000000;
--color-green-primary: limegreen;
--color-primary: var(--color-light-primary);
}

:root[data-theme="green"] {
--color-primary: var(--color-green-primary);
}
ἔρως
ἔρως3w ago
that is a more flexible way to do it
MC23
MC23OP3w ago
It does allow that, this is a partial CSS. There will be a part of the UI where the user can choose the light/dark/system theme, and regarding the colors: it's a landing page, I only need black and white colors :) I'm not setupping a customizable / complex theme like Angular Material or something like that
ἔρως
ἔρως3w ago
that makes sense, but i can't give an opinion about something that isn't there
MC23
MC23OP2w ago
So, when I use SASS how can I use the variables inside this function? Do I need to interpolate them?
ἔρως
ἔρως2w ago
if you show the code, we can answer
MC23
MC23OP2w ago
$colors: (
light: (
text: #181a1b,
bg: #e2e1e1,
btn-border: #181a1b
),
dark: (
text: #e2e1e1,
bg: #181a1b,
btn-border: #e2e1e1
)
);
$colors: (
light: (
text: #181a1b,
bg: #e2e1e1,
btn-border: #181a1b
),
dark: (
text: #e2e1e1,
bg: #181a1b,
btn-border: #e2e1e1
)
);
I wanted to generate dynamic variables to use, but I don't think I can generate SCSS ones but only CSS ones... I'll make an example of two approaches for my font-sizes:
$sizes: (
'xs': 0.75rem,
'sm': 0.875rem,
'md': 1rem,
'lg': 1.125rem,
'xl': 1.25rem
);

@each $size, $value in $sizes {
$fs-#{$size}: $value !global;
}

@function fs($size) {
@return map-get($sizes, $size);
}

.text {
font-size: $fs-md; // doesn't work
font-size: fs('md'); // works
}
$sizes: (
'xs': 0.75rem,
'sm': 0.875rem,
'md': 1rem,
'lg': 1.125rem,
'xl': 1.25rem
);

@each $size, $value in $sizes {
$fs-#{$size}: $value !global;
}

@function fs($size) {
@return map-get($sizes, $size);
}

.text {
font-size: $fs-md; // doesn't work
font-size: fs('md'); // works
}
So if I got things correctly, I should prefer CSS variables when I want something that can be edited at runtime via JS for example, correct?
ἔρως
ἔρως2w ago
you can make this into something so much better lets say you create a module for your settings, like "config" then, you create a module for team related stuff, like "theme" each is an scss file on config, you can expose all the configurations you need then, you can create a base critical.scss file that uses the config module this generates all the variables for the :root and ::backdrop elements
MC23
MC23OP2w ago
Wouldn't this be needed for complex projects? Atm I only have a single SCSS file because I'm working on a very simple landing page. Also this file is not really used since I can only use CSS file in GitHub pages. So I just compile it and then use the generated CSS. I'm kinda familiar with the 7-1 pattern, which I use in Angular
ἔρως
ἔρως2w ago
then, your stuff goes into "theme", where it generates the variable declararions this is just an idea
MC23
MC23OP2w ago
Yeah I'm trying to understand the concept
ἔρως
ἔρως2w ago
but the idea is to generate the variables separated from everything else and everything else just uses the variable when you change a color, a font or something else, you just rebuild the critical css file with all the variables the rest of the code is untouched and the cache still uses those
MC23
MC23OP2w ago
I see, but I can't generate SCSS variables right?
ἔρως
ἔρως2w ago
but all that the functions do is to output specific variables not with scss, no i mean, technically you could, but you need to habe a 2-step rendering compiling first, your scss generates scss files, and then you compile the rest
MC23
MC23OP2w ago
I see. Your approach is needed to address the problem that I have now: I can't use defined SCSS variables inside :root unless I declared them outside Too complex for this base case, but I'll keep it in mind
ἔρως
ἔρως2w ago
it is needlessly complex, but possible the problem is that sass wants do deprecate @import... with @import, you can just have a file with all the variables and just use them normally, and it spits out the value that the sass variable had what you can do is this:
$sizes: (
'xs': 0.75rem,
'sm': 0.875rem,
'md': 1rem,
'lg': 1.125rem,
'xl': 1.25rem
);

:root, ::backdrop {
@each $size, $value in $sizes {
--fs-#{$size}: #{$value};
}
}

@function fs($size) {
@return #{"var(--fs-#{$size})"};
}

.text {
font-size: fs('md'); // works
}
$sizes: (
'xs': 0.75rem,
'sm': 0.875rem,
'md': 1rem,
'lg': 1.125rem,
'xl': 1.25rem
);

:root, ::backdrop {
@each $size, $value in $sizes {
--fs-#{$size}: #{$value};
}
}

@function fs($size) {
@return #{"var(--fs-#{$size})"};
}

.text {
font-size: fs('md'); // works
}
or something like that check it here: https://sass-lang.com/playground/#eJxVj28LgjAQxt/fpzhMUMFJC6KYb/wqprMk3WKbIonfve2iIu7N3e957h/nENv+Ka3AFBCTxSYC98XpaOSYB2BHAucfGVtP+KcarqEq+OGrLwMRApCVAMJo7XIU4lI399boB65Qybq5Ia3OMZ7rYZLYqzewXkdkrLNstxLZBPqMXFsJmw+oukk1rtcKO5uSKaO2ykg3GeX90Vyb9G9KFlE3FE4ujtydVo4FTYQx4TV/8PYCrWJPCA== this works for color too: https://sass-lang.com/playground/#eJxdkN2KwjAQRu/zFEMt2IIR4pUogu+x7EWajm2xppJNZaHk3Z1M6i+5Gb45c5KJUiI3Qz+4vx0UIAD6rmk91VQCePyneqG2SqtqxVHVUIAbVKjmwFtZDa5G9yQpL2Oz1u78pfqYbL7d76pERpUo90IcUZsWct/iBVeQ33Q/orzoK3QW5g1gIvqn1l5Lxg7ZYkoDIfvl5ixh/CFhwUsXMSmNpFHGAj1lSv2wF4GPOJ5Ga3w3WDB9kbgyXeDQj87SSHbTrvgQlRkLxDp+BdOc76JjGbMl7RnuCqlxRA== its just a proof of concept
MC23
MC23OP2w ago
Thank you that's really helpful :Prayge:
ἔρως
ἔρως2w ago
you're welcome as you can see, you dont need to generate scss variables with proper documentation, you can make this a lot more usable too
MC23
MC23OP2w ago
Yeah I'll try to apply this method
Want results from more Discord servers?
Add your server