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;
}