Transition to dynamically created elements

2

I am creating a system to upload images with drag and drop, the idea is that each image is added by appearing in a grid, I use promises so that the image only appears when it is already loaded with the onload event, but not I get it to appear with a smooth transition. I leave a simple example of the problem

let cont = document.getElementById('container')
let btn = document.getElementById('addEl')
btn.addEventListener('click',function(){
  let newEl = document.createElement('div')
  newEl.classList.add('elemento')
  cont.appendChild(newEl)
  newEl.classList.add('visible')
})
#container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 300px;
  background-color: tomato;
}

.elemento {
  width: 50px;
  height: 50px;
  background-color: #1a1a1a;
  opacity: 0;
  transition: opacity 2s ease.in;
}

.visible {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">

</div>
<button type="button" id="addEl">Agregar Elemento</button>

As much as possible, I prefer not to use libraries.

    
asked by Edwin V 17.04.2017 в 04:46
source

1 answer

1

The CSS code is fine (except for your typo% ease.in instead of ease-in ). The reason why it is not yet displayed by adding a delay to the transition ( opacity 2s ease-in 2s ) is due to how an element is rendered in the document.

When you add the element to the DOM programmatically, at that moment information of a state prior to this event is maintained, that is why when you apply the class visible the transition is not made. To make the transition happen, you must force a refinish on the document so that it updates its status.

Example

let cont = document.getElementById('container')
let btn = document.getElementById('addEl')
btn.addEventListener('click',function(){
  let newEl = document.createElement('div')
  newEl.classList.add('elemento')
  cont.appendChild(newEl)
  newEl.clientHeight // forzamos un repintado
  newEl.classList.add('visible')
})
#container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 300px;
  background-color: tomato;
}

.elemento {
  width: 50px;
  height: 50px;
  background-color: #1a1a1a;
  opacity: 0;
  transition: opacity 2s ease-in;
}

.visible {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">

</div>
<button type="button" id="addEl">Agregar Elemento</button>

You can also do this by adding the class after a few milliseconds:

setTimeout(() => newEl.classList.add('visible'), 100);

I do not recommend using the latter because the amount of time for the DOM to be repaired is affected by several factors, which does not allow you to know exactly when it will happen.

The properties that force a repaint are the following:

  • Properties offset : offsetTop , offsetLeft , offsetWidth and offsetHeight .
  • Properties scroll : scrollTop , scrollLeft , scrollWidth and scrollHeight .
  • Properties client : clientTop , clientLeft , clientWidth and clientHeight .
answered by 17.04.2017 / 18:45
source