← All Articles A Product of Kinsa Creative

React Modal Window

In the App.jsx file:

const [modalVisible, setModalVisible] = useState(false);

const toggleModal = () => {
    modalVisible ? setModalVisible(false) : setModalVisible(true);
    document.querySelector('body').classList.toggle('modal-open');
}

const toggleModalViaBgClick = (event) => {
    // This could be DRYed:
    // In order to still be able to use the controls in the modal window
    // we cannot just call toggleModal 
    // b/c we need to be specific about what the event.target is
    // NOTE THAT clicking on the left or right edge of the modal 
    // doesn't trigger this b/c the event.target is the modal content 
    // and not `div.modal` if the width of modal content is set as follows (via hard-coding `80%`)
    // HOWEVER, if the modal content is centered via flexbox, 
    // clicking on the left or right will register a click event on the `.modal` element 
    // and will close the modal window
    if (event.target.className === 'modal visible') {
        modalVisible ? setModalVisible(false) : setModalVisible(true);
        document.querySelector('body').classList.toggle('modal-open');
    }
}

My Modal

Spam and eggs...

In a CSS file:

/* prevent body from scrolling when modal window is open */
body.modal-open {
    height: 100vh;
    overflow: hidden;
}

.modal {
    display: none;

    &.visible {
        background: rgba(0, 0, 0, 0.4);
        display: block;
        height: 100%;
        left: 0;
        overflow: auto;
        position: fixed;
        top: 0;
        width: 100%;
        z-index: 100; /* or some value higher than any other z-index applied */

        .modal-header {
            align-items: center;
            display: flex;
            justify-content: space-between;
            margin-bottom: 1rem;

            button {
                background: transparent;
                border: 0 none transparent;
                color: black;
                font-size: 2rem;
                line-height: 2rem;
                outline: none;
                padding: 0;
            }

            h2 {
                margin-bottom: 0;
            }
        }

        .modal-content {
            background: white;
            margin: 15% auto; /* set to `0 auto` to position to the top edge of the page */
            padding: 2rem;
            width: 80%; /* set to `100%` to go edge-to-edge left-to-right */
        }
    }
}

Centering the Modal Window Vertically

Flexbox

On .modal, change display: block to display: flex and set it to align-items: center to center vertically on the page and justify-content: center to center horizontally on the page. Remove the width of 80% from .modal-content and set the top and bottom margin to 0 instead of 15%.

This works, unless the modal content is bigger than the container in which case it overflows from the center of the window and gets clipped. This happens both vertically and horizontally.

If max-width: 100%; and max-height: 100%; are added to .modal-dialog, the centering is applied but if the window gets to be smaller than the content, it clips from the top left corner rather than the center which is a bit more expected.

Feedback?

Email us at enquiries@kinsa.cc.