'Reverse a transition on props change with styled-components
I am animation two elements on a props change: a container div slides in/out with max-height, and the contents of the div fades in/out with opacity.
Trouble is, I want the container to animate after the contents on the "out" animation, but I want it to appear before the contents on the "in" animation. Currently, the elements always go in the same order: contents transition first, then the container. This means that the contents appear before the container has slid in on the "in" animation.
I've tried using the reverse attribute and keyframes from styled-components, but honestly I'm so bad at CSS animations that I can't begin to understand what I need to change.
Here's the current code:
Component.tsx
export default function Component() {
const [showBanner, setShowBanner] = useState(true);
const handleAccept = () => {
setShowBanner(false);
};
const handleReject = () => {
setShowBanner(false);
};
return (
<StyledComponent $showBanner={showBanner}>
<StyledText>
// some text
</StyledText>
<StyledButtonsContainer>
// some buttons
</StyledButtonsContainer>
</StyledComponent>
);
}
Component.styles.tsx
export const StyledComponent = styled.div<{ $showBanner: boolean }>`
&&& {
position: absolute;
z-index: ${zIndex("overlay")};
display: flex;
flex-direction: column;
max-height: ${(props) => (props.$showBanner ? "100%" : "0")};
height: 100%;
width: 100%;
background: ${(props) => props.theme.secondary};
color: ${(props) => props.theme.white};
transition: max-height 0.5s 0.5s ease;
@media ${device.tablet} {
border-radius: 0 0 2px 20px;
}
* { // targeting everything all of the contents
opacity: ${(props) => (props.$showBanner ? "100%" : "0%")};
transition: opacity 0.5s ease;
}
}
`;
Solution 1:[1]
I sorted this by controlling the transition-delay property with the $showBanner prop. I did it via the transition shorthand, though:
export const StyledCookieBanner = styled.div<{ $showBanner: boolean }>`
&&& {
position: absolute;
z-index: ${zIndex("overlay")};
display: flex;
flex-direction: column;
max-height: ${(props) => (props.$showBanner ? "100%" : "0")};
height: 100%;
width: 100%;
background: ${(props) => props.theme.secondary};
color: ${(props) => props.theme.white};
transition: max-height 0.5s ${(props) => !props.$showBanner && "0.5s"}; // here
@media ${device.tablet} {
border-radius: 0 0 2px 20px;
}
* {
opacity: ${(props) => (props.$showBanner ? "100%" : "0%")};
transition: opacity 0.5s ${(props) => props.$showBanner && "0.5s"}; // here
}
}
`;
This reverses the delays for the two transitions, effectively reversing the transition.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | crevulus |
