CSS Opacity transition with display: none

梦想的初衷 提交于 2021-02-10 05:13:46

问题


I have a menu that I would like to fade in with javascript. I want it to transition from display: none and opacity: 0 to display: flex and opacity: 1. But when I set opacity to 1 using javascript, it doesn't transition, and instead abruptly snaps to 1, whereas If I do not set display to none, it gracefully transitions. I want to use display: none because before the menu appears I need to be able to catch mouse movement on a canvas in the background. I have made a codepen to demonstrate this here.

Note: I want to be able to fade out too using Javascript

I have also taken a look at this question, but the first suggested answer isn't able to fade out.

Thanks!

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>

回答1:


Do not use display: none for elements you want to fade-in. display: none will remove the element from your display. It won't have your css animation applied when it reappears.

Consequently you would have to use JavaScript for the animation. Keep your animation/display logic in your CSS.

There is an old CSS trick where you hide absolute or fixed elements offscreen. using the left property.

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>



回答2:


No JS needed...

You can add an animation css rule and then add keyframes within your CSS that points the animation to your opacity. Name it something like fadeIn and then add an ease and time you wish to have the animation work. Then add @keyframes fadeIn in your css and set the key frames for the opacity to run through a percentage of 0% { opacity: 0; } then 100% { opacity: 1; }. This will add the fade in ease I think you are looking for.

NOTE: Make sure to add multi browser support in your @keyframes css

EDIT: If you're looking to have it fade in and then fade out after a set length of time, tweak the keyframes and animation time setting. See my updated snipit... I also removed the JS opacity: 1 in your setTimeout() as it was forcing the css animation back to 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>



回答3:


As bizarre as it may seem, the answer is to add a line to your code as follows:

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

There's nothing special about this line other than that it performs a 'read' of data within your page (any operation that reads data from the DOM would work). What this does is force the browser to layout (or reflow) the page. This is important because, in general, if you carry out a series of 'write' operations - e.g. adding an element or setting it's style, the browser will batch these up and perform them all at once. This means that when you set the element's opacity to 0, and then to 1, the browser batches up these operations and carries them out together before reflowing the page, and thus there is no animation. By inserting a write operation in between, the browser is able to animate from the state of the element where it is transparent to the state where it is fully opaque.

Making it disappear is a little different:

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

It's best to wait for the previous transition to complete before starting a new one. It's also good practise to remove the event listeners after the event has fired. You have to wait for the transition to complete before removing the element from the DOM. There is no need to carry out a read operation before setting the style that triggers an animation because the page has already been laid out with the opacity set to 1. I have set opacity to 0.1 so that you can see that the element actually disappears.

You can see a JFiddle here.



来源:https://stackoverflow.com/questions/64000697/css-opacity-transition-with-display-none

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!