App Block Theme Extension Modal Popup Contained in Product Info Wrapper

Topic summary

Issue: A modal launched from a Shopify app block on product/cart pages was constrained inside the Product Info Wrapper despite a high z-index, preventing it from overlaying the page.

Context: From product pages, the modal adds the product to cart and then displays the cart; from cart pages, it fetches and displays the current cart. The block’s schema targeted a section for the trigger and attempted to target body for the modal, triggering a warning.

Cause: Modal was rendered within the product section, inheriting its stacking/positioning contexts. Simply increasing z-index was insufficient.

Guidance: Place modal containers at the end of the document (before ) to avoid stacking conflicts; Dawn theme uses this pattern.

Resolution implemented:

  • On DOMContentLoaded, locate the modal container and append it to document.body.
  • Initialize display: none and bind close handlers (button and backdrop clicks).
  • Apply CSS: position: fixed; full-viewport sizing; very high z-index (e.g., 999999); semi-transparent backdrop.

Outcome: Moving the modal container to body and using a very high z-index resolved the overlay issue across tested stores/themes.

Status: Resolved; approach confirmed by multiple participants.

Summarized with AI on December 13. AI used: gpt-5.

I have a modal window that can be launched on a product page or a cart page. On launch from product, the product is added to cart and then the cart is fetched and displayed in a table in the modal window. On launch from cart, the modal window opens and fetches the current cart data.

The extension is an app block button that is dragged into place on product under the Add To Cart button.

When the modal launches, with z-index: 1040, it’s still contained in the Product Info Wrapper.

I suspect it’s because the target for the block is a section in the schema. Not sure why else it would be stuck there. Anyone see this before and have a possible solution?

Hi @c-e-daly :waving_hand: modal implementations typically need the modal container, and thus it’s content, to be copied/moved to before the end tag etc as it’s intialized or triggered.

If not then issues like this occur where you have to fight the containers containers z-index, or everythings positioning.

I think the dawn theme does this behavior with modals so check it as a reference.

Good Hunting.

1 Like

We are testing in 7 stores right now and multiple themes to see if this is a prevalent issue. The modal is triggered by a block and the schema defines a couple of snippets - one for the button targeting a section and one for the modal targeting body (which is throwing a warning so I need to check if body is a target). My thought is that the block being added to the product info container is what contains the modal. I was hoping the z-index would let it “rise above” but that is not the case.

We are having the same issue. Did you happen to solve this? If so how?

We did resolve it. Aside from three global variables in our .js file, the first thing in the code is an event listener for document load and then append the container to the body. This is the code snippet and once we put the modal div in place the problem corrected itself.

The other piece is setting the z-index extremely high

.modal-container{
display: none;
position: fixed;
z-index: 999999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4)
}

and these solved the problem.

// Attach all startup event listeners and initialize logic when DOM is fully loaded
document.addEventListener('DOMContentLoaded', async () => {
    // Initialize modal container and listeners
    const modalContainer = document.getElementById('iwt-modal-container');
    const closeModalButton = document.getElementById('iwt-modal-close-btn');

    if (modalContainer) {
        modalContainer.style.display = 'none';
        document.body.appendChild(modalContainer);

        if (closeModalButton) {
            closeModalButton.addEventListener('click', (event) => {
                event.stopPropagation();
                closeModal();
                console.log('Modal closed with button click.');
            });
        }

        modalContainer.addEventListener('click', (event) => {
            if (event.target === modalContainer) {
                closeModal();
                console.log('Modal closed by clicking outside the modal content.');
            }
        });
    } else {
        console.error('Modal container not found. Check the ID "iwt-modal-container".');
    }
1 Like