20

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 3

24

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>
  );
1
  • Need not the nots(!) you do. This is not working for me. It renders the component with opacity set to 0 or 1. Needs to start at 0 and transition to 1.
    – Rooster242
    Commented Apr 24 at 21:28
4

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>

3
  • This doesn't work well when your using buttons or elements with click events. They may be invisible but they can still be clicked!
    – Mint
    Commented Aug 2, 2021 at 14:40
  • @Mint That's only in the case where you want to rely on just opacity to hide the element. In this case, the elements don't exist in the DOM at all! We're only providing some initial animation at render time, after which they will be visible at all times, so they would anyway be interactive. Commented Aug 2, 2021 at 14:50
  • In any case, that particular issue could also be solved by applying visibility: hidden or pointer-events: none, when opacity is at 0 Commented Aug 2, 2021 at 14:52
1

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.