Zenz
Zenz

Reputation: 31

Get modal fade in in with display block CSS Javascript

I am struggling to get a modal get animated when a button is clicked. The modal must not take space when its hidden. So I want to use display none when its not shown. And when the button is clicked the modal needs to fade in. Now I have found a solution I think to make it work. But still it's not working. Could anyone tell me why its not working? An how I could get it to work?

<!DOCTYPE html>
<html lang="en">
    
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>Document</title>
</head>
    
<body>
  <h2>Animating from <code>display:none</code> to <code>display:block</code></h2>
  <div id="box" class="box"></div>
    
  <button>TOGGLE VISIBILITY</button>
</body>

<script src="script.js"></script>

</html>
.box {
  background: goldenrod;
  width: 300px;
  height: 300px;
  margin: 30px auto;
  transition: all 2s linear;
  display: none;
}
        
.show {
  display: block;
}
          
.visuallyshow {
  opacity: 0;
}
        
button {
  display: block;
  margin: 0 auto;
}
let box = document.getElementById('box'),
  btn = document.querySelector('button');
    
btn.addEventListener('click', function () {
  if (box.classList.contains('show')) {
    box.classList.remove('show');
    setTimeout(function () {
      box.classList.remove('visuallyshow');
    }, 20);
  } else {
    box.classList.add('visuallyshow');
    box.addEventListener('transitionend', function (e) {
      box.classList.add('show');
    }
    // , {
    //   capture: false,
    //   once: true,
    //   passive: false
    // }
    );
  }
}, false);

Upvotes: 0

Views: 2138

Answers (3)

sharben
sharben

Reputation: 129

The problem is that your .box stylesheet does not have "opacity: 0;" by default and that's why it is not transitioning smoothly. Other than that your transition speed is set to 2000 ms which is very slow.

I have made a working solution in this fiddle link: https://jsfiddle.net/32oyu6wf/3/

What I did is I have modified the .box stylesheet to have "opacity: 0;" & adapted the javascript eventlistener to trigger the classes accordingly.

Inspect the fiddle a little and you can re-use the same method in your project.

let box = document.getElementById('box'),
  btn = document.querySelector('button');

btn.addEventListener('click', function() {
  if (box.style.display == "block") {
    box.classList.remove("visuallyshow")
    setTimeout(function() {
      box.style.display = "none"
    }, 210);

  } else {
    box.style.display = "block";
    setTimeout(function() {
      box.classList.add("visuallyshow")
    }, 20);
  }

}, false);
.box {
  background: goldenrod;
  width: 300px;
  height: 300px;
  margin: 30px auto;
  transition: all 0.3s linear;
  display: none;
  opacity: 0;
}

.visuallyshow {
  opacity: 1;
}

button {
  display: block;
  margin: 0 auto;
}
<h2>Animating from <code>display:none</code> to <code>display:block</code></h2>


    <button>TOGGLE VISIBILITY</button>
    <div id="box" class="box"></div>

Upvotes: 1

Michał Perłakowski
Michał Perłakowski

Reputation: 92719

Here's what you need to do:

  • The box should initially have opacity: 0, and the .visuallyshow class should change it to 1.
  • The delay in setTimeout should be 2000, not 20. 2 seconds equals 2000 milliseconds.
  • You need to switch the order of adding and removing classes. When showing the box, you first need to add display: block, and then opacity: 1.
  • When showing the element, instead of using transitionend event handler, you should use setTimeout with 1 ms delay. This will allow the browser to rerender the layout, and so the transition will be able to happen.

let box = document.getElementById('box'),
    btn = document.querySelector('button');

btn.addEventListener('click', function () {

    if (box.classList.contains('show')) {
        box.classList.remove('visuallyshow');
        setTimeout(function () {
            box.classList.remove('show');
        }, 2000);
    } else {
        box.classList.add('show');
        setTimeout(() => {
            box.classList.add('visuallyshow');
        }, 1);
    }

}, false);
.box {
  background: goldenrod;
  width: 300px;
  height: 300px;
  margin: 30px auto;
  transition: opacity 2s linear;
  display: none;
  opacity: 0;
}

.show {
  display: block;
}

.visuallyshow {
  opacity: 1;
}


button {
  display: block;
  margin: 0 auto;
}
<h2>Animating from <code>display:none</code> to <code>display:block</code></h2>
<div id="box" class="box"></div>

<button>TOGGLE VISIBILITY</button>

Upvotes: 1

user16435030
user16435030

Reputation:

.modal {
  display: none;
  opacity: 0;
  transition: opacity: 1s;
}

.modal.show {
  display: block;
  opacity: 1;
}

Should work if you ...classList.add('show') to the modal.

I think the reason yours isn't working is because in order to apply a transition it first needs an initial value before it can know what to transition to. In the above case you first need to tell it that the opacity is 0, after which you can actually "transition" it to 1.

Upvotes: 1

Related Questions