CSS 显示的不透明度过渡:none

CSS Opacity transition with display: none

我有一个菜单,我想用 javascript 淡入。我希望它从 display: noneopacity: 0 过渡到 display: flexopacity: 1。但是当我使用 javascript 将不透明度设置为 1 时,它不会过渡,而是突然捕捉到 1,而如果我没有将显示设置为 none,它会优雅地过渡。我想使用 display: none 因为在菜单出现之前我需要能够在后台的 canvas 上捕捉鼠标移动。我做了一个代码笔来演示这个 here.

注意:我也希望能够使用 Javascript

淡出

我也看过this question,但第一个建议的答案无法淡出。

谢谢!

text = document.getElementById("text");
window.setTimeout((function () {
  text.style.display = "flex";
  text.style.opacity = "1";
}), 2000)
#text {
  display: none;
  opacity: 0;
  width: 500px;
  height: 100px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 3rem;
  color: white;
  align-items: center;
  justify-content: center;
  transition-duration: 2s;
  background-color: black;
  border-radius: 5px;
}
<div id="text">Testing Testing 123</div>

不需要 JS...

您可以添加 animation css 规则,然后在您的 CSS 中添加 keyframes 将动画指向您的 opacity。将其命名为 fadeIn 之类的名称,然后添加您希望动画工作的轻松程度和时间。然后在你的 css 中添加 @keyframes fadeIn 并通过 0% { opacity: 0; } 然后 100% { opacity: 1; } 的百分比将不透明度的关键帧设置为 运行。这将增加我认为您正在寻找的轻松淡入度。

注意:确保在您的@keyframes 中添加多浏览器支持css

编辑:如果您想让它淡入然后在设定的时间长度后淡出,请调整关键帧和动画时间设置。请参阅我更新的 snipit...我还删除了 setTimeout() 中的 JS opacity: 1,因为它迫使 css 动画返回 opacity: 1

Mozilla @keyframes Documentation

text = document.getElementById("text");
window.setTimeout((function() {  
  text.style.display = "flex";
}), 2000)
#text {
  animation: fadeIn ease 5s;
  display: none;
  opacity: 0;
  width: 500px;
  height: 100px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 3rem;
  color: white;
  align-items: center;
  justify-content: center;
  transition-duration: 2s;
  background-color: black;
  border-radius: 5px;
}

@keyframes fadeIn {
  0% {
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
<div id="container">
  <div id="text">Testing Testing 123</div>
</div>

不要对要 fade-in 的元素使用 display: nonedisplay: none 将从您的显示中删除该元素。重新出现时不会应用您的 css 动画。

因此您必须使用 JavaScript 来制作动画。 在 CSS 中保留 animation/display 逻辑。

有一个古老的 CSS 技巧,您可以在屏幕外隐藏 absolutefixed 元素。使用左边 属性.

const text = document.getElementById("text");
window.setTimeout( function() {
  text.classList.remove('hidden');
}, 1000);

window.setTimeout( function() {
  text.classList.add('hidden');
}, 5000)
#text {
  width: 500px;
  height: 100px;
  display: flex;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 3rem;
  color: white;
  align-items: center;
  justify-content: center;
  background-color: black;
  border-radius: 5px;
  opacity: 1;
  transition: opacity 500ms;
}
#text.hidden {
  left: -500000px;
  opacity: 0;
  transition: opacity 500ms, left 0ms 500s;
}
<div id="text" class='hidden'>Testing Testing 123</div>

虽然看起来很奇怪,但答案是在您的代码中添加一行,如下所示:

window.setTimeout((function () {
  text.style.display = "flex";
  document.body.offsetHeight;  // Yes, this line!
  text.style.opacity = "1";
}), 2000);

这一行除了在您的页面中执行 'read' 数据外没有什么特别之处(任何从 DOM 读取数据的操作都可以)。这样做是强制浏览器布局(或重排)页面。这很重要,因为一般来说,如果您执行一系列 'write' 操作 - 例如添加一个元素或设置它的样式,浏览器将把它们分批处理并一次性执行。这意味着当您将元素的不透明度设置为 0,然后再设置为 1 时,浏览器会分批处理这些操作并在回流页面之前将它们一起执行,因此没有动画。通过在两者之间插入写入操作,浏览器能够从元素透明的状态到完全不透明的状态进行动画处理。

让它消失有点不同:

text = document.getElementById("text");

window.setTimeout((function () {
  text.style.display = "flex"; // write operation
  document.body.offsetHeight; // read operation which forces reflow

  text.addEventListener('transitionend', function listener1() {
    text.removeEventListener('transitionend', listener1);
    
    text.addEventListener('transitionend', function listener2() {
      text.removeEventListener('transitionend', listener2);
      text.style.display = 'none'; // remove text
    });
    
    window.setTimeout(function () {
      text.style.opacity = 0.1; // hide text
    }, 1000);
  });
  
  text.style.opacity = 1; // write operation - show text
  
}), 2000);

最好等待上一个转换完成后再开始新的转换。在事件触发后删除事件侦听器也是一种很好的做法。在从 DOM 中删除元素之前,您必须等待转换完成。在设置触发动画的样式之前不需要进行读取操作,因为页面已经布局好,不透明度设置为1。我将不透明度设置为0.1,这样你就可以看到元素实际上消失了。

你可以看到一个JFiddle here.

我的解决方案是在显示和不透明度之间设置 1 毫秒的超时。 我认为所有这些解决方案都有些俗气。 我正在寻找更好的解决方案,但我想有 none.