Define them twice
For now and as far as I can tell you have to define them twice unfortunately. There could absolutely be a best practice however I couldn't find one so this set up works for me.
I add my css vars/ custom properties to specific selectors so they can be modified further per element selector as well as it being slightly easier to inspect each element and have your css vars/ custom properties show with your selector.
Using a preprocessor like sass/scss helps a lot. My usage of this technique is far too lengthy to show all of it, but this is the way.
Example Method 1
// Make a mixin so its easy to repeat
// css vars/ custom properties
@mixin css-vars($var){
--var-bg: #{$var};
}
// Defined before using @include
$var: #fff;
.example {
&,// available to .example
&::before,
&::after {
@include css-vars($var);
background: var(--var-bg);
}
}
Which would output:
.example, .example::before, .example::after {
--var-bg: #fff;
background: var(--var-bg);
}
Example Method 2
Another method would be with nesting mixin includes
that contain the css vars.
@mixin css-vars-generator(
$example-color
) {
// Some cool things could happen here,
// @each loops, color adjustment functions, etc...
--example-color: #{$example-color};
}
@mixin css-vars(
$example-color
) {
// CSS Variables / Custom Properties not inherited or available on psuedo elements from parent elements or :root
// Must include in them in any pseudo you want to use them
&,
& *:before,
& *:after,
& *:hover,
& *:active,
& *:focus {
@include css-vars-generator(
$example-color
);
}
//
}
$example-color:#fff;
.example-parent{
@include css-vars($example-color);
}
Which would ouput:
.example-parent, .example-parent *:before, .example-parent *:after, .example-parent *:hover, .example-parent *:active, .example-parent *:focus {
--example-color: #fff;
}