Creating Multiple Modals on a Single Page

前端 未结 4 835
南笙
南笙 2020-12-15 14:35

I\'m having some issues creating multiple modals on a single webpage following the sample code from w3schools.com. The code in question that I am using is this one: http://w

4条回答
  •  有刺的猬
    2020-12-15 15:13

    Update September 2020: The code in my answer is a slightly outdated version of the one in my blog post. Please view the post itself for the most recent version, along with explanations.

    I know I'm necroing a dead post here, but I'd like to propose a cleaner, more maintainable solution. I wrote an in-depth guide on how to create multiple modals on a single page on my blog. The explanations are a bit involved, so if you want to understand how this code works, I break things down in detail in that post.

    Two versions of the code are below, depending on what you want to accomplish: multiple stacked modals or multiple side-by-side modals.

    I hope this helps anyone who comes across this in the future.

    Creating stacked modals

    // Stack of modals
    let currentlyOpenModals = [];
    
    const noModalsOpen = () => !currentlyOpenModals.length;
    
    const openModal = modalId => {
      const modalWrapper = document.getElementById(modalId);
      modalWrapper.classList.add("visible");
      currentlyOpenModals.push(modalWrapper);
    };
    
    // By definition, it's always the topmost modal that will be closed first
    const closeTopmostModal = () => {
      if (noModalsOpen()) {
        return;
      }
    
      const modalWrapper = currentlyOpenModals[currentlyOpenModals.length - 1];
      modalWrapper.classList.remove("visible");
      currentlyOpenModals.pop();
    };
    
    const modalTriggers = document.querySelectorAll(".modal-trigger");
    modalTriggers.forEach(modalTrigger => {
      modalTrigger.addEventListener("click", clickEvent => {
        const trigger = clickEvent.target;
        const modalId = trigger.getAttribute("data-modal-id");
        openModal(modalId);
      });
    });
    
    // Otherwise, clicking the content of a modal will propagate the click to the modal wrapper,
    // and that will close the entire thing. That's not what we want!
    document.querySelectorAll(".modal-window").forEach(modal => {
      modal.addEventListener("click", clickEvent => {
        clickEvent.stopPropagation();
      });
    });
    
    const modalWrappers = document.querySelectorAll(".modal-wrapper");
    modalWrappers.forEach(modalWrapper => {
      modalWrapper.addEventListener("click", () => {
        closeTopmostModal();
      });
    });
    
    document.querySelectorAll(".close-modal-button").forEach(closeModalButton => {
      closeModalButton.addEventListener("click", () => {
        closeTopmostModal();
      });
    });
    
    document.body.addEventListener("keyup", keyEvent => {
      if (keyEvent.key === "Escape") {
        closeTopmostModal();
      }
    });
    * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
    }
    
    body {
        align-items: center;
        display: flex;
        flex-direction: column;
        font-family: Arial;
        font-size: 18px;
        height: 100vh;
        justify-content: center;
    }
    
    p {
        margin-bottom: 1em;
    }
    
    .modal-wrapper {
        align-items: center;
        background-color: rgba(100, 100, 100, 0.5);
        bottom: 0;
        display: flex;
        flex-wrap: wrap;
        height: 100vh;
        justify-content: center;
        left: 0;
        opacity: 0;
        position: fixed;
        right: 0;
        transition: all 0.2s ease-in-out;
        visibility: hidden;
        width: 100%;
        z-index: 1000;
    }
    
    .modal-wrapper.visible {
        opacity: 1;
        visibility: visible;
    }
    
    .modal-window {
        background-color: white;
        border-radius: 5px;
        box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
        padding: 20px;
        transform: scale(0);
        transition: 0.2s ease-in-out all;
    }
    
    .modal-wrapper.visible .modal-window {
        transform: scale(1);
    }
    
    .modal-header {
        align-items: center;
        border-bottom: 2px solid black;
        display: flex;
        justify-content: space-between;
        margin-bottom: 20px;
        padding-bottom: 20px;
    }
    
    .close-modal-button {
        align-items: center;
        cursor: pointer;
        display: flex;
        height: 30px;
        justify-content: center;
        width: 30px;
    }
    
    .close-modal-button::before {
        content: "X";
        color: rgb(112, 112, 112);
    }
    
    .close-modal-button:hover::before {
        color: black;
    }
    
    .modal-trigger, a {
        color: rgb(10, 47, 255);
        cursor: pointer;
        text-decoration: underline;
    }
    
    
    
        
        
        
        Stacked Modals Demo
    
    
        

    Lorem ipsum. Click this trigger to open a modal.

    Close a modal by clicking off to the side, clicking the X, or pressing Escape.

提交回复
热议问题