How to display or hide component with transition animation in react js

Viewed 9371

I have react component called overlay :

function Overlay({ isOpen }) {
  if (!isOpen) return null;
  return (
    <div
      style={{
        background: "rgba(0,0,0,.7)",
        position: "fixed",
        zIndex: 1,
        top: "0",
        right: "0",
        bottom: "0",
        left: "0",
      }}
    ></div>
  );
}

It gets a prop called isOpen to show itself or hide . The problem is that it appears and disappears suddenly and I want it to have some kind of transition like 1second so it has an animation of appearing and disappearing .

How can I apply transition animation to this component ?

3 Answers

Use opacity instead of display: none. You'll be able to transition it.

setInterval(() => {
  document.querySelector('.box').classList.toggle('hide')
}, 1000)
.box {
  transition: opacity 0.5s ease-in;
  background: crimson;
  color: white;
  opacity: 1;
  padding: 5px 10px;
  display: inline-block;
  font-family: Arial;
}

.hide {
  opacity: 0;
}
<div class="box hide">This is a div</div>

If you don't want the component's appearance to suddenly displace elements after it, I'd recommend rendering it at all times, but keeping it invisible. This is what that would look like:

setInterval(() => {
  document.querySelector('.box').classList.toggle('hide')
}, 1000)
.box, .box2 {
  transition: opacity 0.5s ease-in;
  background: crimson;
  color: white;
  opacity: 1;
  padding: 5px 10px;
  width: fit-content;
  font-family: Arial;
}

.hide {
  opacity: 0;
}

.box2 {
  background: steelblue;
}

.container {
  display: flex;
  flex-direction: column;
}
<div class="container">
<div class="box2"> This is also a div. It will be static </div>
<div class="box hide">This is a div</div>
<div class="box2"> This is also a div. It will be static </div>
<div class="box2"> This is also a div. It will be static </div>
</div>

If you don't want to pre-render it, then you'll have to combine the rendering with a transition, in an animation.

setInterval(() => {
  document.querySelector('.box').classList.toggle('hide')
}, 1000)
.box {
  animation: fade-in 0.5s ease-in;
  background: crimson;
  color: white;
  padding: 5px 10px;
  width: fit-content;
  font-family: Arial;
}

.hide {
  display: none;
}

.box2 {
  background: steelblue;
  color: white;
  padding: 5px 10px;
  width: fit-content;
  font-family: Arial;
}

@keyframes fade-in {
  0% { opacity: 0 }
  100% { opacity: 1 }
}
  

.container {
  display: flex;
  flex-direction: column;
}
<div class="container">
<div class="box2"> This is also a div. It will be static </div>
<div class="box hide">This is a div</div>
<div class="box2"> This is also a div. It will be static </div>
<div class="box2"> This is also a div. It will be static </div>
</div>

If you want to make the appearance even more seamless, you can manipulate the height of the div in the animation:

setInterval(() => {
  document.querySelector('.box').classList.toggle('hide')
}, 1000)
.box {
  animation: fade-in 0.5s ease-in;
  background: crimson;
  color: white;
  padding: 5px 10px;
  width: fit-content;
  font-family: Arial;
}

.hide {
  display: none;
}

.box2 {
  background: steelblue;
  color: white;
  padding: 5px 10px;
  width: fit-content;
  font-family: Arial;
}

@keyframes fade-in {
  0% { opacity: 0; height: 0; }
  100% { opacity: 1; height: 21px; }
}
  

.container {
  display: flex;
  flex-direction: column;
}
<div class="container">
<div class="box2"> This is also a div. It will be static </div>
<div class="box hide">This is a div</div>
<div class="box2"> This is also a div. It will be static </div>
<div class="box2"> This is also a div. It will be static </div>
</div>

I solved the problem by adding opacity and transition and visibility css styles :

return (
    <div
      style={{
        background: "rgba(0,0,0,.3)",
        position: "fixed",
        zIndex: 1,
        top: "0",
        right: "0",
        bottom: "0",
        left: "0",
        opacity: !isOpen ? "0" : "1",
        transition: "all .2s",
        visibility: !isOpen ? "hidden" : "visible",
      }}
    ></div>
  );

Add the transition property:

style={{ ..., transition: "<property> <duration> <movement-pattern>" }}

Eg:

style={{ ..., transition: "right 1s ease-in-out" }}

If you want to apply the transition to all properties (not recommended) then use all for the <property>.

In your case it sounds like you want to have the prop toggle a class "opacity-zero" that has css rule opacity: 0; and the transition rule transition: "opacity 1s ease-in-out".

More on transitions here: https://www.w3schools.com/css/css3_transitions.asp

Related