Activate the sliding animation for closing the modal window

I have successfully implemented a modal using a combination of html, css, and JavaScript. The code snippets are provided below for reference.

One noticeable feature is that the modal window opens with a sliding animation effect from the top.

However, I am looking to enhance the closing transition of the modal by implementing a smooth sliding animation towards the bottom, instead of an abrupt disappearance at its current position.

If anyone could assist in adjusting the codes to achieve this desired effect, it would be greatly appreciated!

let open_modals = [];

(function() {

  // Get the button that opens the modal
  var btn = document.querySelectorAll(".modal-button");

  // All page modals
  var modals = document.querySelectorAll('.modal');

  // Get the <span> element that closes the modal
  var spans = document.getElementsByClassName("close");

  // When the user clicks the button, open the modal
  for (var i = 0; i < btn.length; i++) {
    btn[i].onclick = function(e) {
      e.preventDefault();
      modal = document.querySelector(e.target.getAttribute("href"));
      modal.style.display = "block";
      open_modals.push(modal.id);
    }
  }

  // When the user clicks on <span> (x), close the modal
  for (var i = 0; i < spans.length; i++) {
    spans[i].onclick = function() {
      for (var index in modals) {
        if (typeof modals[index].style !== 'undefined' && modals[index].id == open_modals[open_modals.length - 1]) {
          modals[index].style.display = "none";
          open_modals.pop();
        }
      }
    }
}
})();
@import url('https://fonts.googleapis.com/css?family=Quicksand&display=swap');

/* The Modal (background) */

.modal {
  box-sizing: border-box;
  font-family: 'Quicksand', sans-serif;
  display: none;
  /* Hidden by default */
  position: fixed;
  /* Stay in place */
  z-index: 1;
  /* Sit on top */
  padding-top: 0.1875em;
  /* Location of the box */
  left: 0;
  top: 0;
  width: 100%;
  /* Full width */
  height: 100%;
  /* Full height */
  overflow: auto;
  /* Enable scroll if needed */
  background-color: rgb(0, 0, 0);
  /* Fallback color */
  background-color: rgba(0, 0, 0, 0.4);
  /* Black w/ opacity */
}


.modal-content {
  color: white;
  position: relative;
  background-color: #171B20;
  margin: auto;
  padding: 0;
  border: 0.0625em solid #888;
  width: 97%;
  box-shadow: 0 0.25em 0.5em 0 rgba(0, 0, 0, 0.2), 0 0.375em 1.25em 0 rgba(0, 0, 0, 0.19);
  -webkit-animation-name: animatetop;
  -webkit-animation-duration: 0.4s;
  animation-name: animatetop;
  animation-duration: 0.4s;
}

@-webkit-keyframes animatetop {
  from {
    top: -300px;
    opacity: 0;
  }
  to {
    top: 0;
    opacity: 1;
  }
}

@keyframes animatetop {
  from {
    top: -300px;
    opacity: 0;
  }
  to {
    top: 0;
    opacity: 1;
  }
}

.close {
  color: #F0B823;
  float: right;
  font-size: 9vw;
  font-weight: bold;
  position: absolute;
  right: 0.25em;
  top: -0.25em;
}

.close:hover,
.close:focus {
  color: #fff;
  text-decoration: none;
  cursor: pointer;
}

.modal-header {
  padding: 0.125em 1em;
  background-color: #171B20;
  color: #F0B823;
}

.modal-body {}

// Additional CSS styles omitted for brevity

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<a href="#myModal1" class="modal-button">• Click Me</a>

<div id="myModal1" class="modal">

    <div class="modal-content">
        <div class="modal-header">
            <span class="close">×</span>
            <div class="headertext">
                <p>Modal Header</p>
            </div>
        </div>
        <div class="modal-body">
            <img class="pic" src="https://drive.google.com/thumbnail?id=108ZLeoIfNkKODfRbLuPWpmXRl0gH9qkD">
            <div class="bodytext">
                <p>Body Text Goes Here</p>
            </div>
        </div>
    </div>
</div>

Answer №1

Check out this demo on CodePen

Consider adding more CSS code:

@-webkit-keyframes animateBottom {
  from {
    top: 0px;
    opacity: 1;
  }
  to {
    top: 500px;
    opacity: 0;
  }
}

@keyframes animateBottom {
  from {
    top: 0px;
    opacity: 1;
  }
  to {
    top: 300px;
    opacity: 0;
  }
}
.modal-content-active {

  -webkit-animation-name: animateBottom;
  -webkit-animation-duration: 0.4s;
  animation-name: animateBottom;
  animation-duration: 0.4s;
}

Additionally, make fixes to the JavaScript code:

// When the user clicks on <span> (x), close the modal
for (var i = 0; i < spans.length; i++) {
  // Add your code here
}

//   When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
  // Add your code here
}

A new class .modal-content-active will be created and added to the modal after clicking the close icon. The modal will then be removed after waiting for 0.4 seconds. Hope this information is helpful!

Answer №2

Here is a solution for your issue

$(function() {
  $(".modal-button").on('click', function(e){
    e.preventDefault();
    modal = $($(this).attr("href"));
    modal.css("display", "block");
    modal.animate({
      top: '0',
      opacity: '1'
    }, 400);
  });
  
  $(".close").on('click', function(e){
    e.preventDefault();
    modal = $($(this).closest(".modal"));
    modal.animate({
      top: '300',
      opacity: '0'
    }, 400, function(){
      $(this).css("top", "-300px");
      $(this).css("display", "none");
    });
  });
});
@import url('https://fonts.googleapis.com/css?family=Quicksand&display=swap');

.modal {
  box-sizing: border-box;
  font-family: 'Quicksand', sans-serif;
  display: none;
  position: fixed;
  z-index: 1;
  padding-top: 0.1875em;
  left: 0;
  top: -300px;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgb(0, 0, 0);
  background-color: rgba(0, 0, 0, 0.4);
  opacity: 1;
}

.modal-content {
  color: white;
  position: relative;
  background-color: #171B20;
  margin: auto;
  padding: 0;
  border: 0.0625em solid #888;
  width: 97%;
  box-shadow: 0 0.25em 0.5em 0 rgba(0, 0, 0, 0.2), 0 0.375em 1.25em 0 rgba(0, 0, 0, 0.19);
}

.close {
  color: #F0B823;
  float: right;
  font-size: 9vw;
  font-weight: bold;
  position: absolute;
  right: 0.25em;
  top: -0.25em;
}

.close:hover,
.close:focus {
  color: #fff;
  text-decoration: none;
  cursor: pointer;
}

.modal-header {
  padding: 0.125em 1em;
  background-color: #171B20;
  color: #F0B823;
}

.modal-body {}

.modal-button {
  font-family: 'Quicksand', sans-serif;
  background-color: #171B20;
  border: none;
  color: white;
  padding: 0.248em 0.496em;
  text-align: left;
  text-decoration: none;
  display: inline-block;
  font-size: 7vw;
  margin: 0.124em 0.062em;
  -webkit-transition-duration: 0.4s;
  transition-duration: 0.4s;
  cursor: pointer;
  width: auto;
}

.modal-button:hover {
  background-color: #171B20;
  color: #F0B823;
}

.pic {
  margin: auto;
  display: block;
  height: auto;
  width: 50vh;
}

.headertext {
  font-family: 'Quicksand', sans-serif;
  display: block;
  text-align: center;
  font-size: 6.50vw;
}

.bodytext {
  font-size: 3.90vw;
  font-family: 'Quicksand', sans-serif;
  display: block;
  padding: 0.625em 0.9375em;
}

p {
  display: block;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- Trigger/Open The Modal -->
<a href="#myModal1" class="modal-button">• Click Me</a>

<!-- The Modal -->
<div id="myModal1" class="modal">

    <!-- Modal content -->
    <div class="modal-content">
        <div class="modal-header">
            <span class="close">×</span>
            <div class="headertext">
                <p>Modal Header</p>
            </div>
        </div>
        <div class="modal-body">
            <img class="pic" src="https://drive.google.com/thumbnail?id=108ZLeoIfNkKODfRbLuPWpmXRl0gH9qkD">
            <div class="bodytext">
                <p>Body Text Will Go here</p>
            </div>
        </div>
    </div>
</div>

Answer №3

Include a new class for animation called animationbottom

@keyframes animatebottom {
  from {
    top: 0;
    opacity: 1;
  }
  to {
    top: 300px;
    opacity: 0;
  }
}

Introduce a new class .modal-fade to specify the animation-name.

.modal-fade {
  -webkit-animation-name: animatebottom;
  -webkit-animation-duration: 0.4s;
  animation-name: animatebottom;
  animation-duration: 0.4s;
}

let open_modals = [];

$(function() {

  // Accessing all elements with the class modal-button

  var btn = document.querySelectorAll(".modal-button");

  // All page modals
  var modals = document.querySelectorAll('.modal');

  // Close button within the modal
  var spans = document.getElementsByClassName("close");

  // Open the modal when user clicks the button
  for (var i = 0; i < btn.length; i++) {
    btn[i].onclick = function(e) {
      $("#myModal1").removeClass("modal-fade");
      e.preventDefault();
      modal = document.querySelector(e.target.getAttribute("href"));
      modal.style.display = "block";
      open_modals.push(modal.id);
    }
  }

  // Close the modal when user clicks on close button
  for (var i = 0; i < spans.length; i++) {
    spans[i].onclick = function() {
      for (var index in modals) {
        if (typeof modals[index].style !== 'undefined' && modals[index].id == open_modals[open_modals.length - 1]) {
          $("#myModal1").addClass("modal-fade"); 
          setTimeout(function(){
          $("#myModal1").hide(); 
          open_modals.pop();}, 400);
        }
      }
    }
  }

  // Close the modal when user clicks outside of it
  window.onclick = function(event) {
    
    if (event.target.classList.contains('modal')) {
      for (var index in modals) {
        if (typeof modals[index].style !== 'undefined' && modals[index].id == open_modals[open_modals.length - 1]) {
          modals[index].style.display = "none";
          open_modals.pop();

        }
      }
    }
  }
})
@import url('https://fonts.googleapis.com/css?family=Quicksand&display=swap');

.modal {
  box-sizing: border-box;
  font-family: 'Quicksand', sans-serif;
  display: none;
  /* Hidden by default */
  position: fixed;
  z-index: 1;
  padding-top: 0.1875em;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgb(0, 0, 0);
  background-color: rgba(0, 0, 0, 0.4);
}


.modal-content {
  color: white;
  position: relative;
  background-color: #171B20;
  margin: auto;
  padding: 0;
  border: 0.0625em solid #888;
  width: 97%;
  box-shadow: 0 0.25em 0.5em 0 rgba(0, 0, 0, 0.2), 0 0.375em 1.25em 0 rgba(0, 0, 0, 0.19);
  -webkit-animation-name: animatetop;
  -webkit-animation-duration: 0.4s;
  animation-name: animatetop;
  animation-duration: 0.4s;
}

.modal-fade {
  -webkit-animation-name: animatebottom;
  -webkit-animation-duration: 0.4s;
  animation-name: animatebottom;
  animation-duration: 0.4s;
}

@-webkit-keyframes animatetop {
  from {
    top: -300px;
    opacity: 0;
  }
  to {
    top: 0;
    opacity: 1;
  }
}

@keyframes animatebottom {
  from {
    top: 0;
    opacity: 1;
  }
  to {
    top: 300px;
    opacity: 0;
  }
}

.close {
  color: #F0B823;
  float: right;
  font-size: 9vw;
  font-weight: bold;
  position: absolute;
  right: 0.25em;
  top: -0.25em;
}

.close:hover,
.close:focus {
  color: #fff;
  text-decoration: none;
  cursor: pointer;
}

.modal-header {
  padding: 0.125em 1em;
  background-color: #171B20;
  color: #F0B823;
}

.modal-body {}

.modal-button {
  font-family: 'Quicksand', sans-serif;
  background-color: #171B20;
  border: none;
  color: white;
  padding: 0.248em 0.496em;
  text-align: left;
  text-decoration: none;
  display: inline-block;
  font-size: 7vw;
  margin: 0.124em 0.062em;
  transition-duration: 0.4s;
  cursor: pointer;
  width: auto;
}

/* CSS styles continue... */

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<a href="#myModal1" class="modal-button">• Click Me</a>

<div id="myModal1" class="modal">

    <div class="modal-content">
        <div class="modal-header">
            <span class="close">×</span>
            <div class="headertext">
                <p>Modal Header</p>
            </div>
        </div>
        <div class="modal-body">
            <img class="pic" src="image.jpg">
            <div class="bodytext">
                <p>Body Text Goes Here</p>
            </div>
        </div>
    </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

PHP prepared statements do not seem to be effectively updating or inserting entire datasets

My website allows members to create and update posts using a text editor. However, I've run into an issue when the post content includes new lines or spaces such as <p>&nbsp;</p> or <div>&nbsp;</div>. The problem arises ...

Set containing a nested collection of maps

Recently delving into the world of JavaScript and trying to grasp the concept of maps. This is the code snippet I'm currently working with: const topmap = new Map(); const map1 = new Map(); const map2 = new Map(); const set1 = new Set(); map1.set( ...

Encountering a "Error 404: Page Not Found" message when trying to request a json object from a node server

Working on a RESTful API, I have set it up to run on node.js using express.js, mongodb with mongoose for object modeling, and body-parser for passing HTTP data. However, whenever I start the server and try to access the specified IP address, I encounter a ...

Are you experiencing issues with the .submit() function when used in conjunction with other

Currently, I am working on a survey form that incorporates JQuery to dynamically display or hide fields based on user selections. //FORM CONDITIONALS: This script is responsible for hiding all the helpfulness radios and only displaying them when "Yes" fo ...

A complete guide on executing synchronous HTTP requests while using async.each in Node.js

My goal is to send HTTP requests to APIs, retrieve data for each user, and then insert that data into MongoDB. The issue I'm facing is that all the requests are being made simultaneously, causing the process to get stuck at some point. I'm using ...

Retrieve information through an AJAX or JavaScript request and use it to fill the selected plugin's multiple selection feature

I have searched everywhere for a solution to this problem, but I haven't been able to find any helpful resources. I apologize in advance if this question has been asked before. What I need to do is to display the data from a JSON object that is fetch ...

Overridden CSS rules

Having a slight CSS dilemma. Within my webpage's html, I have the following structure: <div class='box-div'> <div>Entry 1</div> <div class='hide'>Entry 2</div> </div> Here is my associated ...

Perform a function in jQuery only after the previous one has finished running in a cascading manner

Looking for guidance from an expert on how to accomplish this task. I have HTML code for a multiple choice question with options A to E: <div id="correct-answer-XXXXX" style="display:none;"></div> <div id="wrong-answer-XXXXX" style="display ...

Looking for a way to automatically update a map within a Vue component

My component successfully: Receives a string from a sibling input component via the global Bus method in created() => works Manipulates the string into lat/lng coordinates via geoDecoding() => works Resolves promise result coordinates, sets data, a ...

Tips for creating a column with add, edit, and delete buttons in PHP

I found this code on a website that handles pagination and search functionality. However, I am looking to enhance it by adding an icon or button in a column that will allow users to link to the edit and delete functions for specific data selected in the ta ...

Keep the lock engaged during data input to prevent accidental slashes

Incorporating Symfony2.3.4, PHP5.6.3, Twig, HTML5, jQuery2.2.3, and CSS3. I am looking to implement a feature where the slashes (or separators in general) in an input field remain locked as the user enters numbers corresponding to the day, month, and year ...

The REST API endpoint links for Timestamp are displaying a 404 error message indicating they cannot be

After recently diving into backend development, I ran some tests locally using Postman and localhost which seemed to work perfectly. However, upon uploading my code to GitHub, I encountered a 404 error when clicking on the API endpoint hyperlinks from inde ...

Setting up the Angular JS environment manually, without relying on an Integrated

I am a complete beginner when it comes to Angular JS. I recently inherited an Angular JS application that I need to run on a server without using any Integrated Development Environment (IDE). I have tried researching online for methods to run the applicat ...

What are some other options to using position: absolute when working within an inline position:relative?

I've been struggling with this problem for some time now and just can't seem to find a solution. The issue involves a series of position: relative spans enclosing text, along with a position: absolute span set to right: 0;. I expected the second ...

Achieving consistent height for Bootstrap5 columns: A simple guide

I'm currently utilizing Bootstrap5 and I am interested in adjusting the height of these two columns to be similar. Is there a way to achieve this? Below is the code snippet: <link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email ...

Bootstrap - How can I overlay a card onto a jumbotron for the most optimal display?

Currently, I am in the midst of a project and my goal is to position the card on top of the jumbotron. Even though the card will be within the body of the website, I am finding it challenging to achieve this using Bootstrap. The image below provides an exa ...

Guide to implementing if else statements with Protractor

I am facing some unusual situations and I'm not quite sure how to address them. As a newcomer to testing, I've been tasked with testing a website's cart function for proper functionality. The challenge arises when we add a certain number o ...

AngularJS is throwing an error stating that the URL ID is undefined

I am developing an application that utilizes angularjs with codeigniter as the backend. Within my URL, I have http://localhost/submit/1234, with 1234 serving as the ID. Within my angularjs setup: var singlepost = angular.module('singlepost', [ ...

The aesthetic of react-bootstrap and material ui aesthetics is distinctive and visually appealing

As I develop my web application, I have incorporated react-bootstrap for its React components based on Bootstrap. However, wanting to give my project a customized look inspired by Material design, I came across bootstrap-material-design. I am curious if I ...

css problem with stacking order of child elements

Trying to arrange 3 HTML elements on the z-plane: .bank { width: 200px; height: 200px; background-color: grey; position: absolute; z-index: 100; transform: translateY(10%); } .card { width: 100px; height: 100px; background-color ...