Reputation: 1230
I would like to have a flexbox (the container, not the items) animate/transition as it stretches and shrinks to accommodate the different number of items appearing within it. Is there a way to make this possible? I can only find solutions for animating size of items within, not the flexbox itself.
Please see the snippet of scenario below:
const { useState } = React
const App = () => {
const [showSecondDiv, setShowSecondDiv] = useState(true);
return (
<div>
<button onClick={() => setShowSecondDiv(!showSecondDiv)}>{(showSecondDiv? "Shrink" : "Expand") + " flexbox"}</button>
<div className="flex-container">
<div>Hello</div>
{showSecondDiv ? <div>World</div> : null}
</div>
</div>
)
}
ReactDOM.render(<App />,
document.getElementById("root"))
.flex-container {
border-style: solid;
display: flex;
flex-direction: column;
transition: grow 2s;
max-width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root">
<!-- This element's contents will be replaced with your component. -->
</div>
Upvotes: 0
Views: 2366
Reputation: 2372
In your case you won't be able to transition your Flexbox
The auto value is often a very complex case. The specification recommends not animating from and to auto.
From what I understand this also apply to other values that are not fixed.
You can see that there is no transition property that will apply the behavior you're seeking by applying `transition:all 2s'
However here is my attempt at producing the behavior I think you want by animating the max-height of the children element.
const { useState } = React;
const App = () => {
const [showSecondDiv, setShowSecondDiv] = useState(true);
const className = showSecondDiv ? 'grow' : 'shrink';
return (
<div>
<button onClick={() => setShowSecondDiv(!showSecondDiv)}>
{(showSecondDiv ? 'Shrink' : 'Expand') + ' flexbox'}
</button>
<div className="flex-container">
<div>Hello</div>
<div className={className}>World</div>
</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
.flex-container {
border-style: solid;
display: block;
flex-direction: column;
max-width: 100px;
}
.grow {
animation-name: grow;
}
.shrink {
animation-name: shrink;
}
.flex-container > div {
overflow: hidden;
animation-duration: 2s;
animation-fill-mode: forwards;
}
@keyframes grow {
from {
max-height: 0px;
}
to {
max-height: 1rem;
}
}
@keyframes shrink {
from {
max-height: 1rem;
}
to {
max-height: 0px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root">
<!-- This element's contents will be replaced with your component. -->
</div>
Upvotes: 1