Transition not influencing the scale property when activating a class

My modal is not scaling in and out properly when I toggle the 'active' class. It either fully scales out or scales in without any transition.

Example:

const openPopupButtons = document.querySelectorAll('[data-popup-target]');
const closePopupButtons = document.querySelectorAll('[data-close-button]')
const overlay = document.getElementById('overlay')

openPopupButtons.forEach(button, () => {
  button.addEventListener('click', () => {
    const popup = document.querySelector(button.dataset.popupTarget)
    openPopup(popup)
  })
})

closePopupButtons.forEach(button, () => {
  button.addEventListener('click', () => {
    const popup = button.closest('.popup')
    closePopup(popup)
  })
})

function openPopup(popup) {
  if (popup == null) return
  popup.classList.add('active')
  overlay.classList.add('active')
}

function closePopup(popup) {
  if (popup == null) return
  popup.classList.remove('active')
  overlay.classList.remove('active')
}
.popup {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(.75);
  transition: 1s ease-in-out;
  border: 10px double #fff8fb;
  border-radius: 1em;
  padding: 0 1em;
  background-color: #fcdce9;
  width: 600px;
  max-width: 80%;
  z-index: 10;
}

.popup.active {
  transform: translate(-50%, -50%) scale(1);
}

.popup-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: .25rem .5rem;
}

.popup-header .title {
  font-size: 24px;
  font-weight: bold;
}

.popup-header .close-popup {
  cursor: pointer;
  background: none;
  border: none;
  outline: none;
  font-size: 24px;
  font-weight: bold;
}

.post-it {
  border: none;
  border-radius: 1em;
  width: 100%;
  padding: 10px 15px;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  font-size: 16;
}

.popup-footer {
  padding: .5rem 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.create-button {
  border: 3px solid #fff8fb;
  border-radius: 1em;
  background: none;
  outline: none;
  font-size: 18px;
  font-weight: bold;
  padding: 2.5px 20px;
  cursor: pointer;
}

#overlay {
  position: fixed;
  opacity: 0;
  transition: 500ms ease-in-out;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, .5);
  pointer-events: none;
}

#overlay.active {
  opacity: 1;
  pointer-events: all;
}
<body>
  <button data-popup-target="#popup" class="open-popup">Open Pop-up</button>
  <div class="popup active" id="popup">
    <header class="popup-header">
      <div class="title"> Insert Text </div>
      <button data-close-button class="close-popup"> &times; </button>
    </header>
    <div class="popup-body">
      <textarea name="post-it" id="post-it" cols="30" rows="10" class="post-it"></textarea>
    </div>
    <footer class="popup-footer">
      <button class="create-button"> Create </button>
    </footer>
  </div>
  <div class="" id="overlay"></div>
</body>

I'm facing issues with animating the modal on toggle. The hover animation works fine, but transitioning on adding/removing classes doesn't work as expected. I've tried different approaches to define transitions, like specifying properties or transitioning all, but still no luck.

Answer №1

If you're looking for a solution, consider this example that utilizes ES6 syntax:

const overlay = document.getElementById('overlay');
document.querySelectorAll('[data-popup-target]').forEach(button =>
  button.addEventListener('click', openPopup)
);

document.querySelectorAll('[data-close-button]').forEach(button =>
  button.addEventListener('click', closePopup)
);

function openPopup(event) {
  const popupTarget = event.target.dataset.popupTarget;
  const popup = document.querySelector(popupTarget);
  if (!popup) return;
  popup.classList.add('active');
  overlay.classList.add('active');
}

function closePopup(event) {
  const popup = event.target.closest('.popup');
  if (!popup) return;
  popup.classList.remove('active');
  overlay.classList.remove('active');
}
.popup {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(.75);
  transition: 1s ease-in-out;
  border: 10px double #fff8fb;
  border-radius: 1em;
  padding: 0 1em;
  background-color: #fcdce9;
  width: 600px;
  max-width: 80%;
  z-index: 10;
}

.popup.active {
  transform: translate(-50%, -50%) scale(1);
}

.popup-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: .25rem .5rem;
}

.popup-header .title {
  font-size: 24px;
  font-weight: bold;
}

.popup-header .close-popup {
  cursor: pointer;
  background: none;
  border: none;
  outline: none;
  font-size: 24px;
  font-weight: bold;
}

.post-it {
  border: none;
  border-radius: 1em;
  width: 100%;
  padding: 10px 15px;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  font-size: 16;
}

.popup-footer {
  padding: .5rem 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.create-button {
  border: 3px solid #fff8fb;
  border-radius: 1em;
  background: none;
  outline: none;
  font-size: 18px;
  font-weight: bold;
  padding: 2.5px 20px;
  cursor: pointer;
}

#overlay {
  position: fixed;
  opacity: 0;
  transition: 500ms ease-in-out;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, .5);
  pointer-events: none;
}

#overlay.active {
  opacity: 1;
  pointer-events: all;
}
<body>
  <button data-popup-target="#popup" class="open-popup">Open Pop-up</button>
  <div class="popup active" id="popup">
    <header class="popup-header">
      <div class="title"> Insert Text </div>
      <button data-close-button class="close-popup"> &times; </button>
    </header>
    <div class="popup-body">
      <textarea name="post-it" id="post-it" cols="30" rows="10" class="post-it"></textarea>
    </div>
    <footer class="popup-footer">
      <button class="create-button"> Create </button>
    </footer>
  </div>
  <div class="" id="overlay"></div>
</body>

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

When utilizing the .populate() method in Mongoose, how can you retrieve and append ObjectIds with extra attributes to an array (which is returned by .populate()) collected from the

When using the .populate() method in Mongoose, how can I retrieve and add ObjectIds with additional properties to an array (returned by .populate()) if their corresponding document in the collection no longer exists? This question pertains to MongoDB and ...

Using Regular Expression to verify the presence of numbers and spaces

Currently, I have implemented a regular expression that ensures my string contains 5 digits. While this regex works flawlessly, I now also require it to allow white spaces: both "123 45" and "12345" should meet the criteria. string.match(/^\d{5}$/g); ...

What is the best way to populate all data in select2 (4.0) upon page load?

I'm currently utilizing the select2 plugin (v.4.0) and have a specific goal in mind: $("#search-input-chains").select2({ placeholder: "Unit", theme: "bootstrap4", ...

Having trouble with the initial tap not being recognized on your mobile browser?

When using mobile web browsers (specifically chrome and firefox on iOS), I am experiencing an issue where the hamburger menu does not trigger when tapped for the first time. For a simplified version of the HTML/CSS/JS code, you can check it out at: https ...

Past methods: Obsolescence alert and caution

Trying to grasp the concepts of PHP & MYSQL, I have written this code which seems to be functioning properly. However, there are several "warnings" that I am unsure about. Nonetheless, PHP successfully connects to the database. Below are the relevant codes ...

Creating keys for my console.log data and appending it to html in order to display console log results in textboxes

I am currently developing a matching system for Player vs. Player battles and I need to ensure that the keys are appended correctly to my div element. Previously, I have successfully used append with keys before. Below is the code snippet: ...

Transfer or duplicate an SVG image from the bottom div to the top div

Is there a way to move a div from the chart_div to the movehere div? I've tried duplicating it below the current svg, but I'm having trouble targeting just the header row ('g' element) specifically. Here is the HTML: <script type= ...

Is it possible to receive both errors and warnings for the same ESLint rule?

My team is currently in the process of refactoring our codebase, utilizing ESLint to pinpoint any lint errors within our files. Initially, we set high thresholds in one .eslintrc file and have been gradually decreasing these limits as we enhance specific f ...

Is there a way to implement infinite scrolling in my MUI DataGrid component?

Hey there! I have a custom component that needs to have infinite scrolling added to it. I tried looking into MUI DataGrid for solutions, but didn't have much luck implementing anything successfully. Currently, I'm fetching data using GraphQL and ...

Ways to organize JSON data from a fetch request into multiple divisions

I have written a JavaScript code to fetch JSON information. I plan on storing this JSON file locally (I downloaded an example file and added a birthdate object for my usage example from https://jsonplaceholder.typicode.com/users) My goal is to parse the r ...

Accessing clipboard contents upon button click using TypeScript

Seeking assistance with retrieving data from the clipboard in TypeScript after clicking on a button. Please provide guidance. Thank you! ...

How to extract selected value from a dropdown menu in a React component

Is there a way for me to retrieve the chosen value from the dropdown menu? The select dropdown contains 12 options. My goal is to capture the selected value and then utilize it in handlecolumnchange to manipulate the number of columns added or removed. Des ...

Is there a way to apply the active class without relying on an anchor element?

After creating a one-page website, I utilized JavaScript to prevent the hash from appearing in the URL. Here is the HTML code: <ul class="click crsl"> <li><a class="page1 dot active"></a></li> <li><a class=" ...

Updating an AngularJS directive following a service method invocation

My goal is to set up a reusable alert service that can be easily called from anywhere in my application with just: alertService.showAlert('warning', 'something went wrong!'); One example of where I want to use this is after an AJAX ca ...

Using Google's Closure Compiler to Optimize JSON Files

When dealing with a json string that is parsed and properties of the object are accessed using dot notation, a warning may be triggered by the google closure compiler stating that the property is not defined. To overcome this issue, one workaround is to c ...

Unable to open fancybox from a skel-layer menu

Seeking assistance with integrating a Fancybox inline content call from a Skel-layer menu (using the theme found at ) <nav id="nav"> <ul> <li><a href="#about1" class="fancybox fancybox.inline button small fit" >about< ...

Is it advisable to save the text that is utilized in a label?

My journey into web development is just beginning, and I am currently using React JS for my front end development. I have a component that dynamically renders labels based on JSON data, This is how the JSON data looks: data:{ name:"test123" ...

Is there a way to determine if any word within a given text is present in an array?

Imagine you have the following full text: var nation = "Piazza delle Medaglie d'Oro 40121 Bologna Italy" And a given array like: ["Afghanistan", "Italy", "Albania", "United Arab Emirates"] How can we verify if the exact word Italy within that ent ...

Embark on a journey through Express.js routes with a unique context

After grappling with this issue for a few days, my brain feels fried and I can't seem to find the most efficient solution. My ultimate goal is to be able to repeat a route journey with new context data at the start. For example: app.get('/test& ...

What are some ways to sort through JSON data efficiently?

I am in need of filtering JSON data based on specific parameters. When using the GET method at http://localhost:5000/api/car?bodyTypeId=2, I expect to receive only JSON objects with bodyTypeId equal to 2. However, all objects are being returned: [ { ...