Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <h2>fancyBox v3.2 - Morphing modal overlay</h2>

<p>
  Combination of jQuery, CSS transitions to spice up the way modal window opens. 
</p>

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

<div id="morphing-content" class="hidden">
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque auctor nibh eu nibh scelerisque malesuada. Morbi mollis eleifend turpis. Mauris consequat convallis volutpat. Integer quis erat vehicula, molestie nulla vel, sagittis odio. Quisque hendrerit eleifend magna, sit amet dictum odio condimentum a. Proin et ipsum venenatis, elementum sem convallis, pellentesque elit. Mauris congue velit porttitor dui condimentum porttitor. Aenean pretium suscipit ante in imperdiet.
  </p>
  <p>
    Nam vitae suscipit metus, eget volutpat quam. Ut et sem nunc. Vivamus erat leo, auctor in neque non, malesuada consectetur neque. Ut ac purus est. Quisque molestie pharetra sem sit amet ornare. Nam eu felis in nisl lacinia iaculis. Pellentesque ut lobortis lacus. Etiam ut eros non dui ultrices imperdiet.
  </p>
  <p>
    Ut pulvinar sem gravida porta ullamcorper. Pellentesque laoreet tellus eu egestas tempor. Ut nec lobortis nulla. Aenean tincidunt eu eros eget tincidunt. Vivamus ac lacinia mi, ut varius justo. Praesent eu ante vel velit iaculis aliquam sit amet vestibulum purus. Fusce molestie enim eros. Pellentesque justo sem, pharetra vel ligula non, euismod elementum tortor. Morbi dui ligula, rhoncus nec dignissim a, malesuada feugiat massa.
  </p>
  <p>
    Cras non lobortis mauris. Maecenas id placerat est, ac lobortis nisi. Aenean dapibus arcu commodo magna tristique, et facilisis diam aliquam. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce a vestibulum erat, nec ornare libero. Proin aliquam, neque vel mattis euismod, tortor lacus tempus turpis, ac vulputate augue nisl eget sem. Integer in porttitor mauris.
  </p>
</div>
              
            
!

CSS

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

.morphing-btn {
  -webkit-transition: background 0.3s, color 0.2s 0.2s, width 0.2s 0s;
  -moz-transition: background 0.3s, color 0.2s 0.2s, width 0.2s 0s;
  -o-transition: background 0.3s, color 0.2s 0.2s, width 0.2s 0s;
  transition: color 0.3s 0.2s, width 0.2s 0s;
  white-space: nowrap;
  box-sizing: border-box;
}

.morphing-btn_circle {
  color: transparent !important;
  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;
  border-radius: 50%;
  z-index: 3;
  -webkit-transition: all 0.5s cubic-bezier(.65, .05, .36, 1);
  -moz-transition: all 0.5s cubic-bezier(.65, .05, .36, 1);
  -o-transition: all 0.5s cubic-bezier(.65, .05, .36, 1);
  transition: all 0.5s cubic-bezier(.65, .05, .36, 1);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

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

.fancybox-morphing .fancybox-bg {
  background: #FF6666;
  opacity: 1;
}

.fancybox-morphing .fancybox-toolbar {
  top: 20px;
  right: 40px;
}

.fancybox-morphing .fancybox-button--close {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 50%;
  color: #fff;
}

.fancybox-morphing .fancybox-button--close::after, 
.fancybox-morphing .fancybox-button--close::before {
    height: 1.55px;
    width: 22px;
    left: calc(50% - 11px);
}

.fancybox-morphing .fancybox-button--close:hover {
  background: rgba(0, 0, 0, 0.25);
}

/* Styling for element used in example */

#morphing-content {
  margin: 0;
  position: relative;
  background: transparent;
  color: #fff;
  padding: 6em 10vw;
  line-height: 2;
  z-index: 3;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

#morphing-content a {
  color: #fff;
}
              
            
!

JS

              
                // Step 1: Create jQuery plugin
// ============================

$.fn.fancyMorph = function( opts ) {

  var Morphing = function( $btn, opts ) {
    var self = this;

    self.opts = $.extend({
      animationEffect : false,
      infobar    : false,
      buttons    : ['close'],
      smallBtn   : false,
      touch      : false,
      baseClass  : 'fancybox-morphing',
      afterClose : function() {
        self.close();
      }
    }, opts);

    self.init( $btn );
  };

  Morphing.prototype.init = function( $btn ) {
    var self = this;

    self.$btn = $btn.addClass('morphing-btn');

    self.$clone = $('<div class="morphing-btn-clone" />')
      .hide()
      .insertAfter( $btn );

    // Add wrapping element and set initial width used for positioning
    $btn.wrap( '<span class="morphing-btn-wrap"></span>' ).on('click', function(e) {
      e.preventDefault();

      self.start();
    });

  };

  Morphing.prototype.start = function() {
    var self = this;

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

    // Set initial width, because it is not possible to start CSS transition from "auto"
    self.$btn.width( self.$btn.width() ).parent().width( self.$btn.outerWidth() );

    self.$btn.off('.fm').on("transitionend.fm webkitTransitionEnd.fm oTransitionEnd.fm MSTransitionEnd.fm", function(e) {

      if ( e.originalEvent.propertyName === 'width' ) {
        self.$btn.off('.fm');

        self.animateBg();
      }

    }).addClass('morphing-btn_circle');

  };

  Morphing.prototype.animateBg = function() {
    var self = this;

    self.scaleBg();

    self.$clone.show();

    // Trigger repaint
    self.$clone[0].offsetHeight;

    self.$clone.off('.fm').on("transitionend.fm webkitTransitionEnd.fm oTransitionEnd.fm MSTransitionEnd.fm", function(e) {
      self.$clone.off('.fm');

      self.complete();

    }).addClass('morphing-btn-clone_visible');
  };

  Morphing.prototype.scaleBg = function() {
    var self = this;

    var $clone = self.$clone;
    var scale  = self.getScale();
    var $btn   = self.$btn;
    var pos    = $btn.offset();

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

  Morphing.prototype.getScale = function() {
    var $btn    = this.$btn,
        radius  = $btn.outerWidth() * 0.5,
        left    = $btn.offset().left + radius - $(window).scrollLeft(),
        top     = $btn.offset().top  + radius - $(window).scrollTop(),
        windowW = $(window).width(),
        windowH = $(window).height();

    var maxDistHor  = ( left > windowW / 2 ) ? left : ( windowW - left ),
        maxDistVert = ( top > windowH / 2 )  ? top  : ( windowH - top );

    return Math.ceil(Math.sqrt( Math.pow( maxDistHor, 2 ) + Math.pow( maxDistVert, 2 ) ) / radius );
  };

  Morphing.prototype.complete = function() {
    var self = this;
    var $btn = self.$btn;

    $.fancybox.open({ src : $btn.data('src') || $btn.attr('href') }, self.opts);

    $(window).on('resize.fm', function() {
      //self.scaleBg();
    });
  };

  Morphing.prototype.close = function() {
    var self   = this;
    var $clone = self.$clone;

    self.scaleBg();

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

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

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

    $(window).off('resize.fm');
  };

  // Init
  this.each(function() {
    var $this = $(this);

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

  });

  return this;
};


// Step 2: Start using it!
// =======================

$("[data-morphing]").fancyMorph({
  hash : 'morphing'
});


              
            
!
999px

Console