显示块和 css 转换未触发的解决方法

workaround for display block and css transitions not triggering

对于这个问题的这么多更新,我很抱歉,我很高兴大家试图帮助我。我认为下面有一个更清晰的理解这个问题的方法:

CSS 如果您将元素的显示 属性 设置为在更改附加过渡的 属性 之前立即阻止,则

CSS 过渡将不适用。考虑以下代码:

CSS:

#creative {
    display: none;
    opacity: 0;
    transition: opacity 0.5s; 
}

HTML:

<div id="creative">
    <span>Sample text</span>
</div>

Javascript:

var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'block';
dom.creative.style.opacity = 1;

该元素将正确显示,但没有任何过渡。此问题的解决方法是通过访问元素的视觉属性之一强制重绘:

dom.creative.style.display = 'block';
var a = dom.creative.offsetHeight; /* <-- forces repaint */
dom.creative.style.opacity = 1;

有解决这个问题的好方法吗?顺便说一句,我的意思是每次我需要更改显示 属性 和带有过渡的 属性 时,不要添加额外的行 javascript 代码。

没有为 absolute 属性定义转换,例如 display。如何在 noneblock 之间 插入 ?你不能。但是您可以创建一些 post 函数,这些函数将在动画完成后 运行。

使用 setTimeout

您可以使用setTimeout并在动画结束后执行一些代码:

ANIMATION_TIME = 0.5 * 1000; // in ms

function show(element) {
  // Display property must be set inmediatly; otherwise, the 'show' animation won't be visible until it ends.
  element.style.display = 'block';
  element.opacity = 1;
}

function hide(element) {
  element.opacity = 0;

  setTimeout(function() {
    element.style.display = 'none';
  }, ANIMATION_TIME);
}

// Call examples
var dom = {};
dom.creative = document.getElementById('creative');
show(dom.creative);
hide(dom.creative);

使用动画事件

正如@trustk 指出的那样,您还可以(最好)使用 DOM 事件:

function show(element) {
  element.style.display = 'block';
  element.opacity = 1;
  element.removeEventListener("animationend", afterHide, false);
}

function afterHide(e) {
  // e.target -> element
  e.target.display = 'none';
}

function hide(element) {
  element.opacity = 0;
  element.addEventListener("animationend", afterHide, false);
}

如果您只是为不透明度调用添加超时,它应该可以工作!只要不同时调用显示和不透明度属性,持续时间几乎可以为零。

var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'block';
setTimeout(function(){
  dom.creative.style.opacity = 1;
},1);

如果可以选择 jQuery,您也可以使用 jQuery 淡入淡出。然后你可以完全忽略不透明度,就像...

dom.creative.fadeIn(500)

根据您在问题中提供的代码,我将在这里采用完全不同的方式,并使用 animation 代替,这将使整个 repaint问题消失

更新了脚本,将 div 设置为 display: block

var dom = {};
dom.creative = document.getElementById('creative');
dom.creative.style.display = 'none';

var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
  
  if (dom.creative.style.display == 'block') {
    dom.creative.style.display = 'none';    
  } else {
    dom.creative.style.display = 'block';
  }

})
#creative {
  display: none;
  opacity: 0;
  animation: opac 1s forwards;
  margin: 20px;
}
@keyframes opac {
  100% {
    opacity: 1;
  }
}
button {
  margin: 20px;
}
<button id="button">Toggle display</button>

<div id="creative">
  <span>Sample text</span>
</div>

如果不需要 display: none,可以使用 transition 并像这样简单地切换 class

var dom = {};
dom.creative = document.getElementById('creative');

var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
  
  dom.creative.classList.toggle('show');

})
#creative {
  opacity: 0;
  transition: opacity 1s;
  margin: 20px;
}
#creative.show {
  opacity: 1;
  transition: opacity 1s;
}
button {
  margin: 20px;
}
<button id="button">Toggle display</button>

<div id="creative">
  <span>Sample text</span>
</div>

对于transition,除了offsetHeightsetTimeout方案外,还有一个3:rd,视觉效果和toggle display一样block/none,设置 height/width 为 0。

var dom = {};
dom.creative = document.getElementById('creative');

var butt = document.getElementById('button');
butt.addEventListener('click', function(e) {
  
  dom.creative.classList.toggle('show');

})
#creative {
  width: 0;
  height: 0;
  opacity: 0;
  transition: opacity 1s, width 0s 1s;
  margin: 20px 0;
}
#creative.show {
  width: 100%;
  height: auto;
  opacity: 1;
  transition: opacity 1s, width 0s;
}
button {
  margin: 20px 0;
}
<button id="button">Toggle display</button>

<div id="creative">
  <span>Sample text</span>
</div>

<div>Other content</div>

您可以在不使用 javascript 的情况下仅使用 css 过渡来显示/隐藏元素。

<!--html-->
<div id="parent">Some parent text
    <div id="creative">Some details</div>
</div>

/*css*/
#parent #creative{
   opacity:0;
   visibility:hidden;
   clip: rect(0px,0px,0px,0px);
   transition: all 0.5s;
}
#parent:hover #creative{/*trigger transition*/
   opacity:1;
   visibility:visible;
   clip: rect(0px,220px,0px,330px);
}