Home > Mobile >  Animate height changes in div with dynamic content
Animate height changes in div with dynamic content

Time:04-14

I have an application which fetches content from an api and display it in a flex container. With a slider i can navigate through this content. The shown content can have different height and i want to use a smooth animation of the height of my container if my content changes. Because the content i want to show is dynamic i cant use a fixed height of my container and instead i use height 100%. Is there any way to react for changes in height and apply the transistion of e.g. transistion: height 1s Im also open for some javascript solutions but please dont mention any jquery.

Please keep in mind im pretty new to css and especially for animations/transistions.

CodePudding user response:

Just use a keyframes statement like

@keyframes display {
    to {
        display: 100%;
    }
}

and then tell the element to execute the animation like so

#yourElement {
    animation-name: display;
    animation-duration: 1s;
    animation-timing-function: linear;
}

You can replace the animation-timing-function: linear with whatever way you want the animation to look, see Mozilla docs.

CodePudding user response:

This is not an easy task, since transition animates property transition, while if you change the height of an element dynamically by setting it as auto ( it's auto by default ), it can't compute it as an height change, hence there is no transition. As long as I know your best option would be to calculate priorly the height that you need and change it imperatively, but if that can't be done, I've come up to this quite hacky vanilla solution:

const container = document.querySelector('.container');

const data = [
  {
    lines: 10,
  },
  {
    lines: 25,
  },
  {
    lines: 5,
  },
  {
    lines: 35,
  },
  {
    lines: 15,
  },
  {
    lines: 45,
  },
]; 

const offset = 40;

const asyncData = data.map(
  (d, i) => new Promise((res) => setTimeout(() => res(d), 2000 * i))
);

const asyncCycle = async () => {
  for (const d of asyncData) {
    const res = await d;
    const content = Array(res.lines).fill('Hello world').join('');
    console.log('BEFORE MUTATION', container.clientHeight);
    container.style.height = 'auto';
    container.innerHTML = content;
    console.log('AFTER MUTATION 1', container.clientHeight);
    container.style.height = container.clientHeight - offset   'px';
  }
};

const targetNode = container;
const observerOptions = {
  childList: true,
  subtree: true,
};

const observer = new MutationObserver(callback);
observer.observe(targetNode, observerOptions);

function callback(mutationList, observer) {
  mutationList.forEach((mutation, i) => {
    console.log('AFTER MUTATION 2', i, container.clientHeight);
    container.style.height = container.clientHeight   'px';
    /* One or more children have been added to and/or removed
           from the tree.
           (See mutation.addedNodes and mutation.removedNodes.) */
  });
}

// START CYCLE

asyncCycle();
body {
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  width: min(70vw, 300px);
  border-radius: 10px;
  background: orange;
  transition: all 0.2s ease-out;
  padding: 10px;
}
<div ></div>

It makes use of MutationObserver to read dynamically the new height of the container and set it as a style attribute ( that can be transitioned ). It's a bit flawy though and just an idea of how to possibly implement the feature.

  • Related