モーダル高がウィンドウ高より高い場合にスクロールを表示

モーダル実装後によく指摘されるけど、実装時にはあまり考慮されないので備忘録件共有のために書きました。

モーダルの高さがWindowより高い場合に自動的にスクロールさせるようにする

ポイントはlayermodal-wrapperをわけて layermodal-wrapperposition: fixedをつける さらにmodal-wrapperoverflow-y: autoをつけてあげれば自動的にスクロールが表示される

<html>
    <body>
        <button class="jsc-modal-trigger">モーダル</button>
        <div class="layer jsc-layer"></div>
        <div class="modal-wrapper jsc-modal-target">
            <a href="#" class="modal-close jsc-modal-close">×</a>
            <div></div>
        </div>
    </body>
</html>
.is-layer-open {
    overflow: hidden;
}

.layer {
    position: fixed;
    z-index: 1;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: none;
    width: 100%;
    height: 100%;
    margin: auto;
    opacity: 0.9;
    background: #666;
}

.modal-wrapper {
    position: fixed;
    z-index: 2;
    top: 0;
    right: 0;
    bottom: auto;
    left: 0;
    display: none;
    overflow-y: auto;
    width: 50%;
    height: 100%;
    margin: auto;
    background: #fff;
}

.modal-close {
    position: fixed;
}
$(function(){
    MODAL.init();
});
MODAL =  {
    init: function() {
        this.setParameters();
        this.bindEvents();
    },
    setParameters: function() {
        this.$body = $('body');
        this.$layer = $('.jsc-layer');
        this.$trigger = $('.jsc-modal-trigger');
        this.$target = $('.jsc-modal-target');
        this.$close = $('.jsc-modal-close');
    },
    bindEvents: function() {
        var self = this;

        this.$trigger.on('click', function(event) {
            event.preventDefault();
            self.showModal();
        });

        this.$close.on('click', function(event) {
            event.preventDefault();
            self.hideModal();
        });

        this.$layer.on('click', function(event) {
            event.stopPropagation();
            self.hideModal();
        })
    },
    showModal: function() {
        if(this.$layer.is(':animated')) {
            return;
        }
        this.$body.addClass('is-layer-open');
        this.$layer.fadeIn();
        this.$target.fadeIn();
    },
    hideModal: function() {
        if(this.$layer.is(':animated')) {
            return;
        }
        this.$body.removeClass('is-layer-open');
        this.$layer.fadeOut();
        this.$target.fadeOut();
    }
};