One of many newer CSS options that has piqued my curiosity: the light-dark() operate. And I’ve been intently following it ever since it turned Baseline again in Could 2024.
The light-dark() operate, briefly
In the event you don’t know, the light-dark() operate takes two colour arguments: one for mild mode and one for darkish mode. Therefore, the title light-dark(). It toggles between the 2 mild and darkish values based mostly on a consumer’s preferences. Sara Pleasure has an exquisite article the place you may get a way more detailed clarification.
The important thing factor is that the operate requires you to make use of the color-scheme property to activate these two colour modes:
:root {
color-scheme: mild darkish;
}
.factor {
colour: light-dark(brown, black);
}
And, relying on the consumer’s choice, a kind of two modes is utilized.
Simply two modes?
That mentioned, I’ve been questioning for some time now: Ought to the light-dark() operate help greater than mild and darkish colour modes?
I wrote about light-dark() for the CSS-Methods Almanac. Throughout my analysis, I discovered myself wishing the operate might do extra, particularly that it lacks help for different varieties of colour schemes {that a} consumer would possibly want, equivalent to grayscale, excessive distinction, and low distinction.
Does light-dark() even want a high-contrast mode?
I’d say each sure and no. Let’s return in time to when light-dark() was initially proposed someplace round 2022. Emilio Cobos requested for a operate to help mild and darkish mode modifications, and it was added to the specs.
Achieved and dealt with, proper? Not so quick. The ticket was certainly closed when Jacob Miller chimed in:
Simply noticed this from @bramus‘s submit, and I believe that issues are already closed / there’s no altering issues now, however I see this as an method that doesn’t really resolve for the problems individuals are going through with theming, and does so in a manner that may create a entice for them when pursuing correct theming help.
[…]
We shouldn’t ship single-purpose instruments for the browser, however moderately ones that scale and we will construct upon.
Good factor he chimed in, as a result of that prompted Bramus to reopen the ticket:
I feel this was mistakingly carried out so. The top objective is to have one thing like
schemed-value(), withlight-dark()being an middleman step in the direction of the ultimate resolution.
That’s a giant deal! Bramus is saying that the light-dark() operate is an middleman resolution on the best way to a schemed-value() operate. In different phrases, delivery light-dark() was by no means the supposed finish objective. It’s a step alongside the best way to this different extra strong schemed-value() characteristic.
Customized colour schemes
Bramus has already written a bunch in regards to the schemed-value() idea. It might look one thing like this:
:root {
color-scheme: darkish mild {custom};
}
physique {
colour: schemed-value(
mild lightblue, /* Worth used for mild color-scheme */
darkish crimson, /* Worth used for darkish color-scheme */
--custom inexperienced /* Worth used for --custom color-scheme */
);
}
This isn’t doable with light-dark(). In truth, earlier than the operate can help greater than two modes, the color-scheme property must be prolonged with greater than the mild and darkish values. Solely then can light-dark() be prolonged as a result of, keep in mind, light-dark() wants the color-scheme property so as to do its factor.
Particularly, we’d want color-scheme to just accept some type of “{custom}” colour scheme worth. Tab Atkins gives a doable instance within the ticket. The concept is to register a {custom} colour scheme utilizing a @color-scheme at-rule that defines the scheme’s properties, equivalent to what specific colour key phrases are mapped to, after which use that colour scheme’s ident on the color-scheme property that’s declared on the basis factor:
@color-scheme --high-contast {
base-scheme: darkish;
canvascolor: black;
canvastext: white;
accentcolor: white;
/* different properties set to particular colours */
}
html {
color-scheme: --high-contrast;
}
With that in place, the {custom} colour scheme can be utilized as its personal standalone worth within the forthcoming schemed-value() operate:
@color-scheme --high-contast {
/* ... */
}
html {
color-scheme: --high-contrast mild darkish;
}
physique {
colour: schemed-value(--high-contrast, black, white);
}
Breaking all of it down:
- We register a {custom} colour scheme (e.g.
--high-contrast) in a@color-schemeat-rule. - We outline the colour scheme’s properties within the at-rule, equivalent to whether or not its base theme is
mildordarkishand what sure values colour key phrases map to. - We declare the {custom} colour scheme on the
color-schemeproperty on the root stage (i.e.,html { color-scheme: --high-contrast;}). - We apply the {custom} colour scheme by declaring it on color-related properties by the use of the
schemed-value()operate.
So, not solely will light-dark() change, the CSS color-scheme property will most definitely have its personal at-rule to permit for {custom} color-scheme values.
We’d like extra colour theme help, however not in light-dark()
This begs my earlier query: Does the light-dark() operate actually need to help greater than two colour scheme modes? Bramus has a solution:
When
schemed-value()ever turns into a factor,light-dark()would change into syntactic sugar for it.
A-ha! This implies light-dark() doesn’t must help a number of modes as a result of schemed-value() has the ability to increase light-dark() by its personal advantage:
light-dark(<colour>, <colour>); = schemed-value(mild <colour>, darkish <colour>);
Is light-dark() an middleman step? Sure, it’s. And will or not it’s prolonged to help a number of modes, together with {custom} colour schemes? It actually might, however it doesn’t should be. As a substitute, we will register and outline a {custom} colour scheme in an at-rule and ensure the color-scheme property can learn it. That manner, we get the simplicity of a two-mode operate that may be additional abstracted to help further {custom} modes, if wanted.
In truth, it goes past colour schemes. There may be even an open ticket to increase light-dark() for photos, and the discussions surrounding it appear to agree on a brand new operate particularly designed for it.
What about {custom} features?
However, wait! Doesn’t loads of this sound rather a lot like what we’ve been listening to in regards to the work taking place with {custom} features? Certainly, Tab got here again with a doable method utilizing the if() operate, and the Chris Lilley retagged the ticket because of this. That’s when Bramus demonstrated how we might fairly replicate the light-dark() operate with a {custom} CSS operate:
:root {
/* ensures mild mode comes first */
--scheme: mild;
/* darkish mode is about right here */
@media (prefers-color-scheme: darkish) {
--scheme: darkish;
}
}
/* {custom} operate returns any two values relying on whether or not system is in mild or darkish mode */
@operate --light-dark(--light-color, --dark-color) {
consequence: if(model(--scheme: darkish): var(--dark-color) ; else: var(--light-color));
}
p {
font-size: --light-dark(
2rem,
2.5rem
); /* returns 2rem if system is in mild mode and a pair of.5rem if system is in darkish mode */
}
Nothing is about in stone! The one factor we all know for certain is that we’ve got a working light-dark() operate and it’s Baseline broadly accessible to be used. Customized features a piece in progress and solely accessible in Chromium-based browsers on the time I’m penning this.
The trail ahead
I’ve been exploring all the pieces color-related for some time now, and I’d prefer to know your ideas: Are you excited in regards to the upcoming modifications to light-dark()? Do you suppose light-dark() ought to help extra colour modes like excessive distinction?
Let me know your ideas within the remark part beneath. Be at liberty to additionally touch upon any of the W3C GitHub remark threads linked on this submit to share your ideas and considerations for the approaching new options.

