<h2>fancyBox - Morphing modal overlay</h2>

<div style="display: none;" id="hidden-content">
	<h2>Hello!</h2>
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ergo, inquit, tibi Q. At hoc in eo M. Non semper, inquam; Duo Reges: constructio interrete. Bonum liberi: misera orbitas. </p>

<p>Que Manilium, ab iisque M. De illis, cum volemus. Hunc vos beatum; Bestiarum vero nullum iudicium puto. </p>

<p>Itaque fecimus. Ut pulsi recurrant? Quis non odit sordidos, vanos, leves, futtiles? Recte, inquit, intellegis. Verum hoc idem saepe faciamus. </p>
</div>

<a data-morphing class="btn" data-src="#hidden-content" href="javascript:;">Open demo</a>

/* Styling for element used in example */
#hidden-content {
  margin: 0;
  position: relative;
  background: transparent;
  color: #fff;
  width: 50vw;
  padding: 5vh 10vw;
  line-height: 2;
  z-index: 3;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

#hidden-content a {
  color: #fff;
}

/* fancyMorph */

.morphing-btn-wrap {
  text-align: center;
  display: inline-block;
  position: relative;
}

.morphing-btn {
  -webkit-transition: color 0.2s 0.3s, width 0.2s 0s;
  -moz-transition: color 0.2s 0.3s, width 0.2s 0s;
  -o-transition: color 0.2s 0.3s, width 0.2s 0s;
  transition: color 0.2s 0.3s, width 0.2s 0s;
  white-space: nowrap;
  will-change: width, color;
  transform: translate3d(0, 0, 0);
}

.morphing-btn_circle {
  color: transparent;
  padding-left: 0;
  padding-right: 0;
  width: 35.6px !important; /* Override inline style rule */
  -webkit-transition: color 0.2s 0s, width .3s 0.2s;
  -moz-transition: color 0.2s 0s, width .3s 0.2s;
  -o-transition: color 0.2s 0s, width .3s 0.2s;
  transition: color 0.2s 0s, width .3s 0.2s;
}

.morphing-btn-clone {
  position: fixed;
  background: #FF6666;
  width: 3em;
  height: 3em;
  border-radius: 50%;
  z-index: 3;
  font-size: 0.875em;
  -webkit-transition: all 0.6s cubic-bezier(.65,.05,.36,1);
  -moz-transition: all 0.6s cubic-bezier(.65,.05,.36,1);
  -o-transition: all 0.6s cubic-bezier(.65,.05,.36,1);
  transition: all 0.6s cubic-bezier(.65,.05,.36,1);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.morphing-btn-clone_visible {
  -webkit-transform : scale(1) !important;
  -moz-transform : scale(1)  !important;
  -ms-transform : scale(1) !important;
  -o-transform : scale(1)  !important;
  transform : scale(1) !important;

}

.morphing-close {
  position: fixed;
  top: 5%;
  right: 5%;
  background: rgba(0,0,0,0.2);
  text-indent: -9999px;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 0;
  overflow: hidden;
  transition: background-color 0.2s ease 0s, transform .2s ease-in-out;;
  z-index: 99993;
  cursor: pointer;
  outline: none;
}

.morphing-close:active {
  margin-top: -1px;
}

.morphing-close:before,
.morphing-close:after {
  content: "";
  position: absolute;
  left: 12px;
  top: 24px;
  width: 26px;
  height: 1.5px;
  background: #fff;
}

.morphing-close:before {
  -ms-transform: rotate(-45deg);
  -o-transform: rotate(-45deg);
  -webkit-transform: rotate(-45deg);
  -moz-transform: rotate(-45deg);
  transform: rotate(-45deg);
}

.morphing-close:after {
  -ms-transform: rotate(45deg);
  -o-transform: rotate(45deg);
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
}

var Morphing = function( $btn ) {
  this._init( $btn );
};

Morphing.prototype._init = function( $btn ) {
  var that = this;

  that.$btn = $btn.width( $btn.width() ).addClass('morphing-btn');

  // Add wrapping element and set initial width used for positioning
  $btn.wrap(function() {
    var $wrap = $('<div class="morphing-btn-wrap"></div>');

    $wrap.width( $(this).outerWidth( true ) );

    return $wrap;
  });

  that.$clone = $('<div />')
    .hide()
    .addClass('morphing-btn-clone')
    .insertAfter( $btn );

  $btn.on('click', function(e) {
    e.preventDefault();

    that.open();
  });
};

Morphing.prototype.open = function() {
  var that = this;

  if ( that.$btn.hasClass('morphing-btn_circle') ) {
    return;
  }

  // First, animate button to the circle
  that.$btn.one("transitionend.fm webkitTransitionEnd.fm oTransitionEnd.fm MSTransitionEnd.fm", function(e) {
    if ( e.originalEvent.propertyName !== 'width' ) {
      return;
    }

    $(this).off(".fm");

    that._animate();
  });

  that.$btn.width( that.$btn.width() ).addClass('morphing-btn_circle');

};

Morphing.prototype._animate = function() {
  var that   = this;
  var $btn   = that.$btn;
  var $clone = that.$clone;
  var scale  = this._retrieveScale( $btn );
  var pos    = $btn[0].getBoundingClientRect();

  $clone.css({
    top       : pos.top  + $btn.outerHeight() * 0.5 - ( $btn.outerHeight() * scale * 0.5 ),
    left      : pos.left + $btn.outerWidth()  * 0.5 - ( $btn.outerWidth()  * scale * 0.5 ),
    width     : $btn.outerWidth()  * scale,
    height    : $btn.outerHeight() * scale,
    transform : 'scale(' + 1 / scale + ')'
  });

  $clone.one("transitionend.fm webkitTransitionEnd.fm oTransitionEnd.fm MSTransitionEnd.fm", function(e) {
    $(this).off(".fm");

    // Open fancyBox
    $.fancybox.open({ src : $btn.data('src') || $btn.attr('href') }, {
      infobar  : false,
      buttons  : false,
      smallBtn : false,
      touch    : false,
      margin   : 0,
      onInit : function( instance ) {
        instance.$refs.slider_wrap.append('<button class="morphing-close" data-fancybox-close>X</button>');
        instance.$refs.bg.remove();
      },
      afterClose : function() {
        that.close();
      }
    });

  });

  // Trigger expanding of the cloned element
  $clone.show().addClass('morphing-btn-clone_visible');

};

Morphing.prototype.close = function() {
  var that   = this;
  var $btn   = that.$btn;
  var $clone = that.$clone;
  var scale  = that._retrieveScale( $btn );
  var pos    = $btn[0].getBoundingClientRect();

  $clone.css({
    top       : pos.top  + $btn.outerHeight() * 0.5 -  ( $btn.outerHeight() * scale * 0.5 ),
    left      : pos.left + $btn.outerWidth()  * 0.5  - ( $btn.outerWidth()  * scale * 0.5 ),
    width     : $btn.outerWidth()  * scale,
    height    : $btn.outerHeight() * scale,
    transform : 'scale(' + ( 1 / scale ) + ')'
  });

  $clone.one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) {
    $clone.hide();

    $btn.removeClass('morphing-btn_circle');
  });

  $clone.removeClass('morphing-btn-clone_visible');
};

Morphing.prototype._retrieveScale = function( $btn ) {
  var rez = Math.max( $(window).height() * 3 / $btn.height() , $(window).width() * 3 / $btn.width() );

  return rez;
};

$.fn.fancyMorph = function( duration ) {
  this.each(function() {
    var $this = $(this);

    if ( !$this.data('morphing') ) {
      $this.data('morphing', new Morphing( $this ));
    }

  });

  return this;
};

$("[data-morphing]").fancyMorph();

External CSS

  1. https://codepen.io/fancyapps/pen/ygyzop.css
  2. https://codepen.io/fancyapps/pen/oBZXWK.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js
  2. https://codepen.io/fancyapps/pen/ygyzop.js