问题
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