CSS Key-Frames Animating Dynamic Height

css key-frames animating dynamic height

Instead of animating height, try animating transform: translateY() as follows (you will get a true sliding effect):

@keyframes slideDown{
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}

CSS height animation on element with dynamic height

Remove the height: 200px;, so you have both animate for expand and collapse.

Also, use the following to add animate on new line:

@keyframes lineInserted {
from {
height: 0;
}
to {
height: 20px; /* your line height here */
}
}
div[contenteditable] > div {
animation-duration: 0.3s;
animation-name: lineInserted;
transition: height 0.3s;
}

document.querySelector('#button').addEventListener('click', function() {
document.querySelector('.text').classList.toggle('max');
});
.text {
background: green;
color: #fff;
transition: all .3s ease-in-out;
min-height: 20px;
max-height: 90vh;
overflow: auto;
}

.max {
transition: all .3s ease-in-out;
min-height:90vh;
}

@keyframes lineInserted {
from {
height: 0;
}
to {
height: 20px; /* your line height here */
}
}
div[contenteditable] > div {
animation-duration: 0.3s;
animation-name: lineInserted;
transition: height 0.3s;
}
<div class="text" contentEditable="true"></div>
<button id="button">Click</button>

CSS keyframe -- start from dynamic height

Give the list items a max-height and then use transition to get to a min-height when clicked. Use overflow: hidden on the list items to contain items that would push the list item past 100px.

Working Example

In this example, all list items expand on click. Obviously, you would change the javascript to just expand the list item that was clicked.

var expand = document.getElementById("items");
expand.addEventListener('click', function() { this.classList.toggle('click');}, false);
* {  margin: 0;  padding: 0;  list-style: none;}ul {  background: #FF0;  padding: 1px 0;}li {  background: #F00;  margin: 10px;  transition: all 1s;  max-height: 100px;  overflow: hidden;}.click li {  min-height: 200px;}
<ul id="items">  <li>Item</li>  <li>Larger    <br />Item</li>  <li>Largest    <br />Item    <br />In    <br />this    <br />List</li></ul>

How to animate dynamic width content?

You can do this with a keyframe animation. The key is setting a max-width greater than how big the element will be. Note that the animation timing takes into account the total max-width.

CSS

.test {
animation-name: test;
animation-duration: 1s;
animation-direction: forwards;
overflow: hidden;
white-space: nowrap;
}
@keyframes test {
0% {
max-width: 0;
}
100% {
max-width: 200px;
}
}

and then you need to add the class to your dynamic object

function App() {
const [isOpen, setIsOpen] = useState(false);

return (
<div className="container">
<button onClick={() => setIsOpen(!isOpen)}>
{isOpen ? "Hide" : "Show"}
</button>
{isOpen && <div class='test'>Dynamic Content</div>}
<input type="text" />
</div>
);
}

You can toggle the animation duration and make it happen on removal too if you want but I'll leave it to you to play with.

https://codesandbox.io/s/6wj6z1ppxr

CSS keyframe animation for n number of elements

It can only be done in CSS if you hardcode the values (e.g: you know how many items there are). To do it for any number of items, you need js.

Here's a vanilla js class for it:

class BannerAnimation {
#index
el
items
duration = 4000
animationDuration = 420

constructor(props) {
const { start, ...args } = props
Object.assign(this, args)
this.#index = start || 1
if (!this.items || !this.items.length) {
this.items = [...this.el.children].map((c) => c.innerHTML)
}
;[...this.el.children].forEach((c) => c.remove())
this.appendChild(this.#index - 1)
this.el.style.setProperty('--dur', `${this.animationDuration}ms`)
Object.assign(this.el.style, {
display: 'block',
height: this.el.children[0].offsetHeight + 'px'
})
setTimeout(this.start, this.duration)
}

start = () => {
const div = this.appendChild(this.#index)
const first = this.el.children[0]
first.style.marginTop = `-${first.offsetHeight}px`
this.el.style.height = div.offsetHeight + 'px'
this.el.classList.add('animating')
setTimeout(this.end, this.animationDuration)
}

end = () => {
this.el.classList.remove('animating')
this.el.children[0].remove()
this.#index = (this.items.length + this.#index + 1) % this.items.length
setTimeout(this.start, this.duration)
}

appendChild = (i) => {
const div = document.createElement('div')
div.innerHTML = this.items[i]
this.el.appendChild(div)
return div
}
}

new BannerAnimation({
el: banner,
duration: 1000,
// items: [1, 2, 3]
})
#banner {
overflow: hidden;
transition: height 0ms cubic-bezier(.4, 0, .2, 1);
transition-duration: var(--dur);
}
#banner div:first-child {
margin-top: 0px
}
#banner div {
transition: margin-top 0ms cubic-bezier(.4, 0, .2, 1);
transition-duration: var(--dur);
}
<div id="banner">
<div>One</div>
<div>
Two
<div style="height: 100px; border: 1px solid red;"></div>
</div>
<div>Three</div>
<div>Four</div>
<div>Five<br>and a half...</div>
<div>Six</div>
<div>Seven</div>
</div>
<hr>

how to animate width and height 100% using css3 animations?

You need to specifiy 100% of something..in this case, the html/body

* {  margin: 0;  padding: 0;}html,body {  height: 100%;}div {  background: tomato;  width: 100px;  height: 100px;  -webkit-animation: animateThis 1s ease-in;  -webkit-animation-fill-mode: forwards;}@-webkit-keyframes animateThis {  0% {    width: 100px;    height: 100px;  }  100% {    width: 100%;    height: 100%;  }}
<div></div>


Related Topics



Leave a reply



Submit