As @DennisMartinez said,
"CSS custom properties work when cascading. What this means is that it'll work on the element in which it's declared and that elements descendants. A sibling is not a descendant, thus you're faced with this issue."
This means it is really hard to solve this. I believe the following solution is likely to be the best, as the limitation above makes it hard to think of something better.
I ended up declaring the variable twice, once inside the Header styling itself and once inside the sibling selector. I can interpolate this if I want to so I can have a single source of truth still. I wanted the variable to be changed by a media query, so I declared this one twice too, in the same places as the variable. This copy-paste can be extracted into a string and interpolated if I want to.
Here is the code:
export const S_Header = styled.header<HeaderProps>`
--height: 20vw;
position: fixed;
top: 0;
width: 100vw;
height: var(--height);
@media (${devices.medium}) {
--height: 10vw;
}
@media (${devices.large}) {
--height: 5vw;
}
/* Give the next sibling a top padding so it doesn't start underneath the header */
+ * {
--height: 20vw;
padding-top: var(--height);
margin-top: 0;
border-top: 0;
@media (${devices.medium}) {
--height: 10vw;
}
@media (${devices.large}) {
--height: 5vw;
}
}
`;
I also wrote this using the interpolations I mentioned above:
const heightVar = "--height: 20vw;";
const mediaQuery = `
@media (${devices.medium}) {
--height: 10vw;
}
@media (${devices.large}) {
--height: 5vw;
}
`;
export const S_Header = styled.header<HeaderProps>`
${heightVar}
position: fixed;
top: 0;
width: 100vw;
height: var(--height);
z-index: 98;
transform: ${(props): string =>
props.visible === false ? "translateY(-100%)" : "none"};
background-color: ${(props): string =>
props.atTop ? "transparent" : props.bgColor};
transition: transform 0.35s, background-color 0.35s ease-in-out;
${mediaQuery}
/* Give the next sibling a top padding so it doesn't start underneath the header */
+ * {
${heightVar}
padding-top: var(--height);
margin-top: 0;
border-top: 0;
${mediaQuery}
}
`;