Adding multiple modals to a page

I am working with this modal that I like but I am able to place only one modal to the page. I have unsuccessfully attempted to add a second one (or multiples). Can this be done by essentially using the same code with minor changes?

What I want to add is a second or third “information2.asp” or “information3.asp”. This obviously place the text into the modal. Works great for the first one!

Any help would be appreciated.

Thank you.

<a href="#" data-open-modal>Information</a>
<div class="modal-overlay">
  <div class="modal-inner">
    <div class="modal-container">
      <div class="modal-header">
        <a href="#" class="modal-close">&times;</a>
      </div>
      <div class="modal-content">
      <!--#INCLUDE FILE="information.asp"-->
      </div>
    </div>
  </div>
</div>
html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
.modal-overlay {
  position: fixed;
  top:0; left:0;
  display: none;
  width: 100%;
  height: 100%; /*treated as min-height in display table*/
  background-color: rgba(0, 0, 0, .5);
  opacity: 0;
  transition: opacity .2s ease;
}
.modal-overlay.active {
  display: table;
}
.modal-overlay.visible {
  opacity: 1;
}
.modal-inner {
  display: table-cell;
  vertical-align: middle;
}
.modal-container {
  margin: 0 auto;
  width: 50%;
  min-width: 750px;
  max-width: 850px;
  max-height: 600px;
  overflow: auto;
  border: 1px solid;
  background: #fff;
  border-radius: 5px;
}
.modal-header {
  text-align: right;
}
.modal-close {
  margin-right: .25em;
  color: inherit;
  text-decoration: none;
  font-size: 2rem;
  font-weight: bold;
}
.modal-content {
  padding: 0 10px;
}
.modal-content p {
  margin: 0 0 1em;
}

/*-- removed inline styles from p tag--*/
p.open {
  margin: 1em;
  text-align: center;
  font-size: 1em;
  font-weight: 600;
  color: #4c659b;
  text-transform: uppercase;
  font-family: Arial, Helvetica, sans-serif;
window.onload = function () {
    var openModal = document.querySelector('[data-open-modal]')
    var closeModal = document.querySelector('.modal-close')
    var modalOverlay = document.querySelector('.modal-overlay')
    var modalInner = document.querySelector('.modal-inner')

    var handleShowModal = function (event) {
        modalOverlay.classList.add('visible')
    }

    var handleHideModal = function (event) {
        modalOverlay.classList.remove('active')
    }

    var handleOpenModal = function (event) {
        event.preventDefault()
        modalOverlay.classList.add('active')

        // Wait a tick to kickoff the animation
        window.setTimeout(handleShowModal)
    }

    var handleCloseModal = function (event) {
        if (event.target !== event.currentTarget) {
            // Only hide the modal when clicking elements the handler
            // got actually attached to, not others from which the
            // event bubbles up to the target (e.g. the modal content)
            return;
        }

        event.preventDefault()
        modalOverlay.classList.remove('visible')

        // Hide the modal when the fading out is finished
        modalOverlay.addEventListener(
    'transitionend',
    handleHideModal, {
        once: true,
        passive: true
    }
  )
    }

    openModal.addEventListener('click', handleOpenModal)
    closeModal.addEventListener('click', handleCloseModal)
    modalInner.addEventListener('click', handleCloseModal)

} //]]>


2 Likes

Maybe.

Could you please make a minimal demo of the lightbox in action and post a link to it here. This should contain only the code necessary for the lightbox to run.

1 Like

Can you explain what you mean or want? That’s all the code that I use for the modal to work. The asp file just holds the text and has no code in it. When I click on the a href link the asp file goes to the modal. If this clarifies, I am not using images, just text in the asp file.

Oh ok. In that case, I guess you can do it like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Modal demo</title>
    <style>
      html {
        box-sizing: border-box;
      }
      *, *:before, *:after {
        box-sizing: inherit;
      }
      .modal-overlay {
        position: fixed;
        top:0; left:0;
        display: none;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, .5);
        opacity: 0;
        transition: opacity .2s ease;
      }
      .modal-overlay.active {
        display: table;
      }
      .modal-overlay.visible {
        opacity: 1;
      }
      .modal-inner {
        display: table-cell;
        vertical-align: middle;
      }
      .modal-container {
        margin: 0 auto;
        width: 50%;
        min-width: 750px;
        max-width: 850px;
        max-height: 600px;
        overflow: auto;
        border: 1px solid;
        background: #fff;
        border-radius: 5px;
      }
      .modal-header {
        text-align: right;
      }
      .modal-close {
        margin-right: .25em;
        color: inherit;
        text-decoration: none;
        font-size: 2rem;
        font-weight: bold;
      }
      .modal-content {
        padding: 0 10px;
      }
      .modal-content p {
        margin: 0 0 1em;
      }
      .hide{
        display: none;
      }
      p.open {
        margin: 1em;
        text-align: center;
        font-size: 1em;
        font-weight: 600;
        color: #4c659b;
        text-transform: uppercase;
        font-family: Arial, Helvetica, sans-serif;
    </style>
  </head>
  <body>
    <a href="#" data-open-modal data-modal="1">Modal 1</a><br>
    <a href="#" data-open-modal data-modal="2">Modal 2</a>

    <div class="modal-overlay">
      <div class="modal-inner">
        <div class="modal-container">
          <div class="modal-header">
            <a href="#" class="modal-close">&times;</a>
          </div>
          <div class="modal-content-1 hide">
            Hello from modal 1
          </div>
          <div class="modal-content-2 hide">
            Hello from modal 2
          </div>
        </div>
      </div>
    </div>

    <script>
      window.onload = function () {
        var [...openModalLinks] = document.querySelectorAll('[data-open-modal]')
        var closeModal = document.querySelector('.modal-close')
        var modalOverlay = document.querySelector('.modal-overlay')
        var modalInner = document.querySelector('.modal-inner')
        var modalContent = document.querySelector('.modal-inner')
        var [...modalContent] = document.querySelectorAll('div[class^="modal-content-"]')

        var handleShowModal = function (id) {
          modalOverlay.classList.add('visible')
          modalOverlay.querySelector(`.modal-content-${id}`).classList.remove('hide')
        }

        var handleHideModal = function (event) {
          modalOverlay.classList.remove('active')
        }

        var handleOpenModal = function (event) {
          var id = event.target.getAttribute('data-modal');

          event.preventDefault()
          modalOverlay.classList.add('active')

          window.setTimeout(handleShowModal(id))
        }

        var handleCloseModal = function (event) {
          if (event.target !== event.currentTarget) {
            return;
          }

          event.preventDefault()
          modalOverlay.classList.remove('visible')
          modalContent.forEach(modal => modal.classList.add('hide'));

          modalOverlay.addEventListener(
            'transitionend',
            handleHideModal, {
              once: true,
              passive: true
            }
          )
        }

        openModalLinks.forEach(link => link.addEventListener('click', handleOpenModal))
        closeModal.addEventListener('click', handleCloseModal)
        modalInner.addEventListener('click', handleCloseModal)
      }
    </script>
  </body>
</html>

Try that out and let me know if it works.

2 Likes

That works, thanks.

  1. I have users still using IE11. Can a minor tweak be made for that to happen?

  2. Your example places the 2 links together. I would probably have more uses when the links are in different areas of the page. How can those be separated? And, does your example work with multiple links?

Thanks

Oh, bad luck. You can always run the code through this to make it compatible.

Alternatively, change the following lines:

var [...openModalLinks] = document.querySelectorAll('[data-open-modal]')
var [...modalContent] = document.querySelectorAll('div[class^="modal-content-"]')

to:

var openModalLinks = Array.prototype.slice.call(document.querySelectorAll('[data-open-modal]'))
var modalContent = Array.prototype.slice.call(document.querySelectorAll('div[class^="modal-content-"]'))

The links can be anywhere on the page.

With some slight tweaking, for sure. Why not give it a try?

Of course, yes I was looking at the modal-content by mistake, obvious that the links can be moved!

I will check that out and I think I can see where that change is made.

I will look at the compiler. Changing that doesn’t work.

James, thank you.

1 Like

In analyzing your version from the one that I originally submitted is a nice tutorial for adding additional links, which I tried and was successful at adding those link. Pretty simple and easy to follow.

I was comparing the css and JS between the 2 of them and it looks like there is enough difference which is the reason you can use other links to the same code with minor additions. Like:

<div class="modal-content-3 hide">

and the

<a href="#" data-open-modal data-modal="3">Modal 3</a>

Since my code was working in IE11, I was attempting to alter my code, but per my comments above, it’s not really feasible to do.

I don’t really understand the compiler and the code enough to make yours to work in IE11.

Thanks

Would it be possible to add/remove attributes, like ‘aria-hidden’ or ‘tabindex’, using this code?

I am not sure what that means but if you mean you want more than one modal to show at a time then by the common definition of modal you are not making the windows modal. Modal usually means only one at a time. As best as I can tell everything you are doing is modal in name only, but calling the CSS and other stuff modal might be confusing for others that look at the code and/or others that might help you.

So what is working and what isn’t? Is the version using two modals working in IE 11?

The version I submitted works fine in IE11. Your version which I prefer because it is easy to add multiple links is the one that I am struggling with to work in IE11. When you clink on the link the modal doesn’t open.

Thanks!

This will work:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Modal demo</title>
    <style>
      html {
        box-sizing: border-box;
      }
      *, *:before, *:after {
        box-sizing: inherit;
      }
      .modal-overlay {
        position: fixed;
        top:0; left:0;
        display: none;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, .5);
        opacity: 0;
        transition: opacity .2s ease;
      }
      .modal-overlay.active {
        display: table;
      }
      .modal-overlay.visible {
        opacity: 1;
      }
      .modal-inner {
        display: table-cell;
        vertical-align: middle;
      }
      .modal-container {
        margin: 0 auto;
        width: 50%;
        min-width: 750px;
        max-width: 850px;
        max-height: 600px;
        overflow: auto;
        border: 1px solid;
        background: #fff;
        border-radius: 5px;
      }
      .modal-header {
        text-align: right;
      }
      .modal-close {
        margin-right: .25em;
        color: inherit;
        text-decoration: none;
        font-size: 2rem;
        font-weight: bold;
      }
      .modal-content {
        padding: 0 10px;
      }
      .modal-content p {
        margin: 0 0 1em;
      }
      .hide{
        display: none;
      }
      p.open {
        margin: 1em;
        text-align: center;
        font-size: 1em;
        font-weight: 600;
        color: #4c659b;
        text-transform: uppercase;
        font-family: Arial, Helvetica, sans-serif;
    </style>
  </head>
  <body>
    <a href="#" data-open-modal data-modal="1">Modal 1</a><br>
    <a href="#" data-open-modal data-modal="2">Modal 2</a>

    <div class="modal-overlay">
      <div class="modal-inner">
        <div class="modal-container">
          <div class="modal-header">
            <a href="#" class="modal-close">&times;</a>
          </div>
          <div class="modal-content-1 hide">
            Hello from modal 1
          </div>
          <div class="modal-content-2 hide">
            Hello from modal 2
          </div>
        </div>
      </div>
    </div>

    <script>
      window.onload = function () {
        var openModalLinks = Array.prototype.slice.call(document.querySelectorAll('[data-open-modal]'));
        var closeModal = document.querySelector('.modal-close');
        var modalOverlay = document.querySelector('.modal-overlay');
        var modalInner = document.querySelector('.modal-inner');
        var modalContent = document.querySelector('.modal-inner');
        var modalContent = Array.prototype.slice.call(document.querySelectorAll('div[class^="modal-content-"]'));

        var handleShowModal = function (id) {
          modalOverlay.classList.add('visible');
          modalOverlay.querySelector('.modal-content-' + id).classList.remove('hide');
        }

        var handleHideModal = function (event) {
          modalOverlay.classList.remove('active');
        }

        var handleOpenModal = function (event) {
          var id = event.target.getAttribute('data-modal');

          event.preventDefault();
          modalOverlay.classList.add('active');

          window.setTimeout(handleShowModal(id));
        }

        var handleCloseModal = function (event) {
          if (event.target !== event.currentTarget) {
            return;
          }

          event.preventDefault();
          modalOverlay.classList.remove('visible');
          modalContent.forEach(function(modal) { modal.classList.add('hide') });

          modalOverlay.addEventListener(
            'transitionend',
            handleHideModal, {
              once: true,
              passive: true
            }
          );
        }

        openModalLinks.forEach(function(link) {  link.addEventListener('click', handleOpenModal) });
        closeModal.addEventListener('click', handleCloseModal);
        modalInner.addEventListener('click', handleCloseModal);
      }
    </script>
  </body>
</html>
2 Likes

Yes it does! And again, thank you very much. Great modal example, especially when you want to have more than one to a page.

Appreciated very much!

1 Like

One thing that I don’t like about modals, and perhaps because I haven’t figured it out, how do you print JUST what is in the modal?

With onclick="window.open and a sized window (and I know this is being replaced by modals) all that prints is the page that is in the window.

So my question is, without additional coding to the main page, is there code that when I have an include file in the modal, and I have a print button on that information, how can I just print that information and not the underlying page?

I’m on the hop right now, but look into print stylesheets.

https://www.smashingmagazine.com/2011/11/how-to-set-up-a-print-style-sheet/

I don’t disagree with your point and I am trying to take my onclick="window.open’s and convert them into modals. Most are instructional information and I do track the frequency of the “Print this page” clicks, and they are numerous.

Will look into your link as from what I can determine, it’s different with modals. I will explore.

Thanks

Hi,

I’m still not actually sure what you are trying to achieve.

You have various modals on various pages and you would like people to be able to print them. Did I get that right?

Yes.

I know how to do a media=print, display:none on the main page so when you print the contents of the modal the main page is hidden and not printed.

So what I was saying, and my thoughts, is that most users don’t know the difference between a new page on the screen vs a modal; they never will. The user thinks that if it on the screen it can be printed if they want it, whether it has a print button or not - just right click and print.

It’s not up to me to decide whether they want to print it or not. Most users don’t really know even how to take a screen shot of the modal and then save it. So they print it. I don’t want the user to think that I have a lousy website that when they print a modal it looks all messed up because it’s printing the underlying page.

I am looking at this as a business man and not a developer who has superior knowledge. Therefore, I think that all modals should have the ability to print just the information in the modal by not having to hide the page beneath it.

Therefore, it would be good as a practical design and common use that with a modal, since it often has a white background and looks printable, it should be printable. That’s all!

Actually it’s surprising to me that modals weren’t set up that way in the beginning of it’s use. It just makes sense to me to do it that way. I was looking at some example of that on Stackover, but they do look rather complex. I am going to see what I can come up with to use it as a standard with your really nice example of multiple modals to the page. It would seem, but I am sure it’s not, rather simple to wrap some code in the CSS on the modal content and then wrap code in the div’s on the main page with the modals to accomplish this. So still looking into to that. Sorry for the long explanation, but I hope I have clarified my point.

So you want to print the contents of the modal when its open, but print the rest of the page when it’s not. Is that right?

If so, I don’t think you’re going to get around using JavaScript.

Here’s an example using Bootstrap: https://jsfiddle.net/ozkary/3zu008ch/