Reputation: 5421
I enjoy using CSS custom properties, but there's this thing that I often find that I wish I could do.
I wish to be able to apply some styles conditionally based on the value of a CSS custom property. Here's some pseudo-code:
.something {
border: var(--is-dark-theme) ? 1px solid : none;
}
I understand that custom properties do not work like this. But may be there is some other way that I'm not aware of that could help me achieve a similar result?
Or perhaps there is some spec proposal that would this possible in the future?
Upvotes: 19
Views: 18295
Reputation: 796
Just FYI: The following is not working today (2023-02-06), but someday in future there might be this very nice CSS feature called container style queries:
/* not working today (2023-02-06), maybe in future */
@container style(--theme: dark) {
.box {
border: 1px solid #aaa;
}
}
Upvotes: 8
Reputation: 796
Here's an alternative version of my demo above, using Thorgeir's genius answer (I've added those extra .container
divs to make the solution a bit better understandable):
.light-theme {
--theme: light;
}
.dark-theme {
--theme: dark;
}
.container {
container: var(--theme) / inline-size;
}
.text-box {
font-family: Helvetica, Arial, sans-serif;
padding: 1rem;
color: black;
background-color: #f4f4f4;
border: none;
}
@container dark (min-width: 0) {
.text-box {
color: white;
background-color: black;
border: 5px solid #aaa;
}
}
<div class="light-theme">
<div class="container">
<div class="text-box">light theme</div>
</div>
</div>
<div class="dark-theme">
<div class="container">
<div class="text-box">dark theme</div>
</div>
</div>
Upvotes: 3
Reputation: 272816
Here is another idea similar to Ori Drori's answer where I rely on the use of an invalid value inside border to remove the border. This can be useful in case you want to use keywords like false
/true
/yes
/no
.something {
border: var(--is-dark-theme,2px) solid black;
}
<div class="something">Dark theme</div>
<div class="something" style="--is-dark-theme: false">Light theme</div>
Upvotes: 12
Reputation: 4433
This code enables you to apply a class based on a CSS property of a parent. So by applying a different CSS to a parent element, you can change the class applied to a child element:
.outer:hover {
container-name: dark;
container-type: inline-size;
}
.inner{background-color:silver;color:black;}
@container dark (min-width: 0px) {
.inner{background-color:#333;color:white}
}
<div class="outer">
<div class="inner">inner</div>
</div>
Here we have element with the class name .inner
, By default it has a silver background and white text color.
Above it we have a parent element with the class name .outer
.
the .outer
class no styles by default, but on hover we set the container-name
to dark
.
We can the target the .inner
element when it's inside an element that has the container-name:dark
and use an always true predicate that is (min-width: 0px)
Upvotes: 3
Reputation: 796
In cases where you have something like "condition xyz is on
or off
" (like in the light theme vs dark theme example) you can use the following CSS trick (I know this looks completely weird if you see this trick for the first time, but in contrast to the tricks presented in the other answers, this one will work for all CSS properties):
For each on/off condition define two custom properties, one for the 'on' case, one for the 'off' case. Instead of on
use the value initial
, instead of off
use value
(space character).
.light-theme {
--is-light-theme: initial;
--is-dark-theme: ;
}
.dark-theme {
--is-light-theme: ;
--is-dark-theme: initial;
}
div {
font-family: Helvetica, Arial, sans-serif;
padding: 1rem;
color:
var(--is-light-theme, black)
var(--is-dark-theme, white);
background-color:
var(--is-light-theme, #f4f4f4)
var(--is-dark-theme, black);
border:
var(--is-light-theme, none)
var(--is-dark-theme, 5px solid #aaa);
}
<div class="light-theme">
light theme
</div>
<div class="dark-theme">
dark theme
</div>
Upvotes: 6
Reputation: 191976
You can sometimes use calc()
to get roughly similar results. In this case if --is-dark-theme
is 0 or 1, you can multiply it by the width
of border, to show or hide it:
.something {
border: calc(var(--is-dark-theme) * 1px) solid black;
}
<div class="something" style="--is-dark-theme: 1">Dark theme</div>
<div class="something" style="--is-dark-theme: 0">Light theme</div>
Upvotes: 7