Preguntas similares se han hecho aquí en varias formas de complejidad. Algunos usan jQuery:

Cómo alternar animación con pantalla css: ninguno.

Y algunos muy específicos que pasan por alto el alcance y la simplicidad de lo que se intenta lograr:

JavaScript: agregue la transición entre display: none y display: block.

Pero tome este código muy simplificado, por ejemplo:

var button = document.getElementsByTagName( 'button' )[ 0 ],
    div = document.getElementsByTagName( 'div' )[ 0 ];

button.addEventListener( 'click', toggleVisibility );

function toggleVisibility(){
  if( 
    div.classList.contains( 'show' ) 
   ){
    div.classList.remove( 'show' );
    div.classList.add( 'hide' );
  }
  else {
    div.classList.add( 'show' );
    div.classList.remove( 'hide' );
  }
}
div {
  height: 100px;
  width: 100px;
  background: #000;
  transition: 1s;
}

.hide {
  opacity: 0;
}

.show {
  opacity: 1;
}
<p>A square</p>

<div class="show"></div>

<br>

<button>click to toggle hide/show</button>

Esto alterna con éxito la opacidad. Pero tan pronto como agrego display: none a la clase .hide el efecto se rompe horriblemente:

var button = document.getElementsByTagName( 'button' )[ 0 ],
    div = document.getElementsByTagName( 'div' )[ 0 ];

button.addEventListener( 'click', toggleVisibility );

function toggleVisibility(){
  if( 
    div.classList.contains( 'show' ) 
   ){
    div.classList.remove( 'show' );
    div.classList.add( 'hide' );
  }
  else {
    div.classList.add( 'show' );
    div.classList.remove( 'hide' );
  }
}
div {
  height: 100px;
  width: 100px;
  background: #000;
  transition: 1s;
}

.hide {
  display: none; /* added "display:none" in this example */
  opacity: 0;
}

.show {
  opacity: 1;
}
<p>A square</p>

<div class="show"></div>

<br>

<button>click to toggle hide/show</button>

¿Cuál es una solución simple y reutilizable que podemos usar sin ningún complemento o biblioteca para desvanecer primero, luego apagar display y primero encender display y luego desvanecer?

Editar: estoy usando display sobre visibility porque en este ejemplo, como en la mayoría de los casos uso este efecto, quiero que el elemento se elimine por completo, ya que generalmente está encima de otros elementos obstaculizando los efectos mouseover / click.

2
sol acyon 16 feb. 2017 a las 06:54

4 respuestas

La mejor respuesta

Agregar pointer-events a tu clase .hide debería ser el truco.

.hide {
  pointer-events: none;
  opacity: 0;
}
0
Venky Soorisetty 16 feb. 2017 a las 04:12

Agregue un detector de eventos en transitionend para cambiar la propiedad de visualización; no puede hacer la transición, ya que solo cambia elementos de modo a otro. Entonces, si desea cambiar la visualización, hágalo antes / después de que comience la transición.

var button = document.getElementsByTagName( 'button' )[ 0 ],
    div = document.getElementsByTagName( 'div' )[ 0 ];

button.addEventListener('click', toggleVisibility)
div.addEventListener('transitionend', function() {
    if (this.classList.contains('hide')) {
        this.style.display = 'none'
    }
})

function toggleVisibility(){
    if (div.classList.contains( 'show' )) {
        div.classList.remove( 'show' );
        div.classList.add( 'hide' );
    }
    else {
        div.style.display = 'block'
        div.classList.add( 'show' );
        div.classList.remove( 'hide' );
    }
}




div {
  height: 100px;
  width: 100px;
  background: #000;
  transition: 1s;
}

.hide {
  opacity: 0;
}

.show {
  opacity: 1;
}

EDITAR : esto no funciona muy bien en la transición de hide => show, me acabo de dar cuenta. Otra posible solución que solucionaría sus problemas con la visibilidad es, no solo cambiar la propiedad de visibilidad, sino también cuando está oculta, simplemente agregue un z-index: -10, o algo así (tal vez un número no tan ridículo). Eso es, se mantiene fuera del camino en lo que respecta a las capas, y no afectará las transiciones. (Es posible que esto no funcione bien si necesita eliminar el elemento del diseño, pero eso no se ha aclarado).

0
thesublimeobject 16 feb. 2017 a las 04:15

¿Es esto lo que estás buscando? Desvanecerse y luego desaparecer con display:none.

var button = document.getElementsByTagName( 'button' )[ 0 ],
    div = document.getElementsByTagName( 'div' )[ 0 ];

button.addEventListener( 'click', toggleVisibility );

function toggleVisibility(){
  if( 
    div.classList.contains( 'show' ) 
   ){
    div.classList.remove( 'show' );
     setTimeout(function(){
         div.classList.add( 'hide' );
     }, 500);
  }
  else {
    div.classList.remove( 'hide' );
     setTimeout(function(){
         div.classList.add( 'show' );
     }, 0); //Yeah it needs a 1 tick delay to work.
  }
}
div {
  opacity: 0;
  height: 100px;
  width: 100px;
  background: #000;
  transition: opacity 1s ease;
}
.hide {
   display:none;
}

.show {
  opacity: 1;
}
<div class="show"></div>

<button>click to toggle hide/show</button>
1
Zed 16 feb. 2017 a las 04:11

Establezca visibilty en lugar de display, y si desea establecer la sincronización, puede establecer el atributo de transición en all (transition:all 1s).

código

div {
  height: 100px;
  width: 100px;
  background: #000;
  transition: visibility 0s, opacity 0.5s linear;
}

.hide {
  visibility: hidden;
  opacity: 0;
}

.show {
  visibility: visible;
  opacity: 1;
}
0
Rach Chen 16 feb. 2017 a las 04:03