如何切换显示:none/display:block while first animating/transitioning

How to toggle display:none/display:block whilst first animating/transitioning

这里以各种复杂的形式提出了类似的问题。一些使用 jQuery:

还有一些非常具体的内容忽略了要实现的目标的范围和简单性:

.

但是以这个非常精简的代码为例:

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>

这成功地切换了不透明度。但是,一旦我将 display: none 添加到 .hide class 中,效果就会非常糟糕:

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>

有什么简单的、可重复使用的解决方案,我们可以在没有任何插件或库的情况下使用,先淡出,然后关闭 display,然后先打开 display,然后淡入?

编辑: 我在 visibility 上使用 display 因为在这个例子中,在大多数情况下我使用这种效果,我希望元素完全删除为它通常位于阻碍 mouseover/click 效果的其他元素之上。

transitionend 上添加事件侦听器以更改显示 属性;它不能转换,因为它只是将元素从一种模式更改为另一种模式。因此,如果您想更改显示,请执行此操作 before/after 转换开始。

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;
}

编辑:这在从隐藏 => 显示的过渡中效果不是很好,我刚刚意识到。解决可见性问题的另一种可能的解决方案是,不仅改变可见性 属性,而且当它被隐藏时,只需添加一个 z-index: -10 或类似的东西(可能不是那么荒谬的数字).就您的分层而言,它不会妨碍您,并且不会影响过渡。 (如果您需要从布局中删除元素,这可能效果不佳,但尚未阐明。)

设置visibilty而不是display,如果你想设置同步,你可以将过渡属性设置为all(transition:all 1s).

代码

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

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

.show {
  visibility: visible;
  opacity: 1;
}

pointer-events 添加到您的 .hide class 应该可以解决问题。

.hide {
  pointer-events: none;
  opacity: 0;
}