One of many newer CSS options that has piqued my curiosity: the light-dark() perform. And I’ve been intently following it ever since it grew to become Baseline again in Might 2024.
The light-dark() perform, briefly
In case you don’t know, the light-dark() perform takes two shade arguments: one for gentle mode and one for darkish mode. Therefore, the identify light-dark(). It toggles between the 2 gentle and darkish values based mostly on a person’s preferences. Sara Pleasure has a beautiful article the place you will get a way more detailed clarification.
The important thing factor is that the perform requires you to make use of the color-scheme property to activate these two shade modes:
:root {
color-scheme: gentle darkish;
}
.factor {
shade: light-dark(brown, black);
}
And, relying on the person’s desire, a type of two modes is utilized.
Simply two modes?
That mentioned, I’ve been questioning for some time now: Ought to the light-dark() perform help greater than gentle and darkish shade modes?
I wrote about light-dark() for the CSS-Tips Almanac. Throughout my analysis, I discovered myself wishing the perform may do extra, particularly that it lacks help for different kinds of shade schemes {that a} person would possibly choose, resembling 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 perform to help gentle and darkish mode adjustments, and it was added to the specs.
Accomplished and dealt with, proper? Not so quick. The ticket was certainly closed when Jacob Miller chimed in:
Simply noticed this from @bramus‘s put up, and I believe that issues are already closed / there’s no altering issues now, however I see this as an strategy that doesn’t truly clear up for the problems individuals are dealing with with theming, and does so in a method that may create a lure for them when pursuing correct theming help.
[…]
We shouldn’t ship single-purpose instruments for the browser, however relatively 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 completed so. The tip purpose is to have one thing like
schemed-value(), withlight-dark()being an middleman step in the direction of the ultimate answer.
That’s an enormous deal! Bramus is saying that the light-dark() perform is an middleman answer on the best way to a schemed-value() perform. In different phrases, transport light-dark() was by no means the supposed finish purpose. It’s a step alongside the best way to this different extra sturdy schemed-value() characteristic.
Customized shade schemes
Bramus has already written a bunch concerning the schemed-value() idea. It may look one thing like this:
:root {
color-scheme: darkish gentle {custom};
}
physique {
shade: schemed-value(
gentle lightblue, /* Worth used for gentle color-scheme */
darkish crimson, /* Worth used for darkish color-scheme */
--custom inexperienced /* Worth used for --custom color-scheme */
);
}
This isn’t potential with light-dark(). The truth is, earlier than the perform can help greater than two modes, the color-scheme property must be prolonged with greater than the gentle and darkish values. Solely then can light-dark() be prolonged as a result of, bear in mind, light-dark() wants the color-scheme property with a view to do its factor.
Particularly, we’d want color-scheme to simply accept some form of “{custom}” shade scheme worth. Tab Atkins offers a potential instance within the ticket. The concept is to register a {custom} shade scheme utilizing a @color-scheme at-rule that defines the scheme’s properties, resembling what explicit shade key phrases are mapped to, after which use that shade scheme’s ident on the color-scheme property that’s declared on the foundation 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} shade scheme can be utilized as its personal standalone worth within the forthcoming schemed-value() perform:
@color-scheme --high-contast {
/* ... */
}
html {
color-scheme: --high-contrast gentle darkish;
}
physique {
shade: schemed-value(--high-contrast, black, white);
}
Breaking all of it down:
- We register a {custom} shade scheme (e.g.
--high-contrast) in a@color-schemeat-rule. - We outline the colour scheme’s properties within the at-rule, resembling whether or not its base theme is
gentleordarkishand what sure values shade key phrases map to. - We declare the {custom} shade scheme on the
color-schemeproperty on the root degree (i.e.,html { color-scheme: --high-contrast;}). - We apply the {custom} shade scheme by declaring it on color-related properties by means of the
schemed-value()perform.
So, not solely will light-dark() change, the CSS color-scheme property will more than likely have its personal at-rule to permit for {custom} color-scheme values.
We’d like extra shade theme help, however not in light-dark()
This begs my earlier query: Does the light-dark() perform actually need to help greater than two shade 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 have to help a number of modes as a result of schemed-value() has the ability to increase light-dark() by its personal advantage:
light-dark(, ); = schemed-value(gentle , darkish );
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} shade schemes? It actually may, but it surely doesn’t should be. As a substitute, we will register and outline a {custom} shade scheme in an at-rule and ensure the color-scheme property can learn it. That method, we get the simplicity of a two-mode perform that may be additional abstracted to help further {custom} modes, if wanted.
The truth is, it goes past shade 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 perform particularly designed for it.
What about {custom} features?
However, wait! Doesn’t quite a lot of this sound quite a bit like what we’ve been listening to concerning the work occurring with {custom} features? Certainly, Tab got here again with a potential strategy utilizing the if() perform, and the Chris Lilley retagged the ticket because of this. That’s when Bramus demonstrated how we may fairly replicate the light-dark() perform with a {custom} CSS perform:
:root {
/* ensures gentle mode comes first */
--scheme: gentle;
/* darkish mode is about right here */
@media (prefers-color-scheme: darkish) {
--scheme: darkish;
}
}
/* {custom} perform returns any two values relying on whether or not system is in gentle or darkish mode */
@perform --light-dark(--light-color, --dark-color) {
consequence: if(fashion(--scheme: darkish): var(--dark-color) ; else: var(--light-color));
}
p {
font-size: --light-dark(
2rem,
2.5rem
); /* returns 2rem if system is in gentle 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 a working light-dark() perform and it’s Baseline broadly out there to be used. Customized features a piece in progress and solely out there in Chromium-based browsers on the time I’m scripting this.
The trail ahead
I’ve been exploring the whole lot color-related for some time now, and I’d prefer to know your ideas: Are you excited concerning the upcoming adjustments to light-dark()? Do you assume light-dark() ought to help extra shade 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 put up to share your ideas and considerations for the approaching new options.









