JSFiddle - React, Tailwind, and code Playground

A modal concept with a visible level of depth between the page and modal layers.

by Jennifer Perrin

HTML

<div class="avgrund-contents">
  <h1>Avgrund</h1>
  <p>
        A modal concept with a visible level of depth between the page and modal layers. Click a button below to give it a try.
    </p>
    <button onclick="avgrund.activate( 'stack' );">Stack it</button>
    <button onclick="avgrund.activate();">Grow it</button>
    <p>
        Uses CSS transforms to scale components and CSS filters to blur the page.
    </p>
    <p>
        <em>Avgrund</em> is Swedish for abyss.
    </p>
</div>

<div class="avgrund-cover"></div>

<div class="avgrund-popup">
    <h2>That's all, folks</h2>
    <p>
        You can hit ESC or click outside to close the modal. Give it a go to see the reverse transition.
    </p>
    <button onclick="avgrund.deactivate();">Close</button>
</div>

CSS

* {
  margin: 0;
    padding: 0;
}

html, 
body {
    height: 100%;
    overflow: hidden;
}

html {
    background-color: #222;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAGklEQVQIW2NkYGD4D8SMQAwGcAY2AbBKDBUAVuYCBQPd34sAAAAASUVORK5CYII=);
    background-repeat: repeat;
}

h1, 
h2 {
    font-size: 24px;
}

p {
    margin: 10px 0 10px 0;
    font-size: 16px;
    line-height: 1.32;
}

a {
    color: #7aa76d;
    text-decoration: none;

    -webkit-transition: 0.15s color ease;
       -moz-transition: 0.15s color ease;
        -ms-transition: 0.15s color ease;
         -o-transition: 0.15s color ease;
            transition: 0.15s color ease;
}
    a:hover {
        color: #91cd85;
    }

small {
    display: block;
    margin-top: 15px;
    padding-top: 15px;
    color: #333;
    font-size: 0.85em;
    border-top: 1px dashed #ccc;

    -webkit-text-size-adjust: none;
}

button {
    border: 0px;
    padding: 8px 10px;
    margin: 5px 0px;
    border-radius: 1px;

    cursor: pointer;
    color: #fff;
    background: #7aa76d;
    font-size: 15px;

    -webkit-transition: 0.15s background ease;
       -moz-transition: 0.15s background ease;
        -ms-transition: 0.15s background ease;
         -o-transition: 0.15s background ease;
            transition: 0.15s background ease;
}
    button:hover {
        background: #91cd85;
    }
    button:active {
        background: #60895a;
    }
    button+button {
        margin-left: 5px;
    }

.sharing {
    margin-top: 50px;
}

body {
    background: #fff;

    font-family: 'Lato', Helvetica, sans-serif;
    font-size: 16px;
    color: #222;
}
    .avgrund-active body {
        -webkit-transform: scale( 0.9 );
           -moz-transform: scale( 0.9 );
            -ms-transform: scale( 0.9 );
             -o-transform: scale( 0.9 );
                transform: scale( 0.9 );
    }

.avgrund-cover {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
   ...

JavaScript

(function(){

  var container = document.documentElement,
        popup = document.querySelector( '.avgrund-popup' ),
        cover = document.querySelector( '.avgrund-cover' ),
        currentState = null;

  addClass( container, 'avgrund-ready' );

    // Deactivate on ESC
    function onDocumentKeyUp( event ) {
        if( event.keyCode === 27 ) {
            deactivate();
        }
    }

    // Deactivate on click outside
    function onDocumentClick( event ) {
        if( event.target === cover ) {
            deactivate();
        }
    }

    function activate( state ) {
        document.addEventListener( 'keyup', onDocumentKeyUp, false );
        document.addEventListener( 'click', onDocumentClick, false );

        removeClass( popup, currentState );
        addClass( popup, 'no-transition' );
        addClass( popup, state );

        setTimeout( function() {
            removeClass( popup, 'no-transition' );
            addClass( container, 'avgrund-active' );
        }, 0 );

        currentState = state;
    }

    function deactivate() {
        document.removeEventListener( 'keyup', onDocumentKeyUp, false );
        document.removeEventListener( 'click', onDocumentClick, false );

        removeClass( container, 'avgrund-active' );
    }

    function disableBlur() {
        addClass( document.documentElement, 'no-blur' );
    }

    function addClass( element, name ) {
        element.className = element.className.replace( /\s+$/gi, '' ) + ' ' + name;
    }

    function removeClass( element, name ) {
        element.className = element.className.replace( name, '' );
    }

    window.avgrund = {
        activate: activate,
        deactivate: deactivate,
        disableBlur: disableBlur
    }

})();