enmi12/glossaire/_posts/custom-layout-modes/2012-01-03-masonry-column-shift.html
author ymh <ymh.work@gmail.com>
Mon, 08 Sep 2025 19:44:41 +0200
changeset 23 417f20492bf7
parent 0 d970ebf37754
permissions -rwxr-xr-x
Update Docker configuration and plugin versions - Upgrade MariaDB from 10.6 to 11 with auto-upgrade support - Add WordPress debug environment variable to FPM container - Update PHP-FPM Dockerfile base image - Update Include Mastodon Feed plugin with bug fixes and improvements - Update Portfolio plugin (v2.58) with latest translations and demo data enhancements - Remove old README.md from Mastodon Feed plugin 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>

---
title: Masonry Column Shift
layout: default
category: custom-layout-modes
---

<style>
  .shifty-item {
    width: 210px;
    margin: 10px;
    float: left;
    background: #AAA;
    border: 5px solid white;
  }

  .shifty-item:hover { z-index: 10; }

  .shifty-item.h1 { height: 140px; background: #66F; }
  .shifty-item.h2 { height: 200px; background: #F66; }
  .shifty-item.h3 { height: 240px; background: #6F6; }
  .shifty-item.h4 { height: 280px; background: #FF6; }

</style>

<section id="copy">
  <p>Custom layout mode <code>masonryColumnShift</code>. Enabled columns of a Masonry layout to be shifted and not affect other columns. After the size of an item element has changed, you can trigger a special <code>columnShiftOfItem</code> method that will push the column down. This layout only works with item elements that have the same width</p>

{% highlight javascript %}

var $container = $('#container');

$container.isotope({
  itemSelector: '.shifty-item',
  layoutMode: 'masonryColumnShift'
});

$container.find('.shifty-item').hover(
  function() {
    $(this).css({ height: "+=100" });
    // note that element is passed in, not jQuery object
    $container.isotope( 'shiftColumnOfItem', this );
  },
  function() {
    $(this).css({ height: "-=100" });
    $container.isotope( 'shiftColumnOfItem', this );
  }
);

{% endhighlight %}

</section>


<div id="container">
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h4"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h3"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h4"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h4"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h3"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h4"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h4"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h3"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h4"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h1"></div>
  <div class="shifty-item h2"></div>

</div> <!-- #container -->


<script src="../{{ site.jquery_js }}"></script>
<script src="../{{ site.isotope_js }}"></script>
<script>


  // -------------------------- Masonry Column Shift -------------------------- //
  
  // custom layout mode
  $.Isotope.prototype._masonryColumnShiftReset = function() {
    // layout-specific props
    var props = this.masonryColumnShift = {
      columnBricks: []
    };
    // FIXME shouldn't have to call this again
    this._getSegments();
    var i = props.cols;
    props.colYs = [];
    while (i--) {
      props.colYs.push( 0 );
      // push an array, for bricks in each column
      props.columnBricks.push([])
    }
  };
  
  $.Isotope.prototype._masonryColumnShiftLayout = function( $elems ) {
    var instance = this,
        props = instance.masonryColumnShift;
    $elems.each(function(){
      var $brick  = $(this);
      var setY = props.colYs;

      // get the minimum Y value from the columns
      var minimumY = Math.min.apply( Math, setY ),
          shortCol = 0;

      // Find index of short column, the first from the left
      for (var i=0, len = setY.length; i < len; i++) {
        if ( setY[i] === minimumY ) {
          shortCol = i;
          break;
        }
      }

      // position the brick
      var x = props.columnWidth * shortCol,
          y = minimumY;
      instance._pushPosition( $brick, x, y );
      // keep track of columnIndex
      $.data( this, 'masonryColumnIndex', i );
      props.columnBricks[i].push( this );

      // apply setHeight to necessary columns
      var setHeight = minimumY + $brick.outerHeight(true),
          setSpan = props.cols + 1 - len;
      for ( i=0; i < setSpan; i++ ) {
        props.colYs[ shortCol + i ] = setHeight;
      }

    });
  };
  
 $.Isotope.prototype._masonryColumnShiftGetContainerSize = function() {
    var containerHeight = Math.max.apply( Math, this.masonryColumnShift.colYs );
    return { height: containerHeight };
  };

  $.Isotope.prototype._masonryColumnShiftResizeChanged = function() {
    return this._checkIfSegmentsChanged();
  };
  
  $.Isotope.prototype.shiftColumnOfItem = function( itemElem, callback ) {
    
    var columnIndex = $.data( itemElem, 'masonryColumnIndex' );
    
    // don't proceed if no columnIndex
    if ( !isFinite(columnIndex) ) {
      return;
    }

    var props = this.masonryColumnShift;
    var columnBricks = props.columnBricks[ columnIndex ];
    var $brick;
    var x = props.columnWidth * columnIndex;
    var y = 0;
    for (var i=0, len = columnBricks.length; i < len; i++) {
      $brick = $( columnBricks[i] );
      this._pushPosition( $brick, x, y );
      y += $brick.outerHeight(true);
    }

    // set the size of the container
    if ( this.options.resizesContainer ) {
      var containerStyle = this._masonryColumnShiftGetContainerSize();
      containerStyle.height = Math.max( y, containerStyle.height );
      this.styleQueue.push({ $el: this.element, style: containerStyle });
    }

    this._processStyleQueue( $(columnBricks), callback )

  };

  $(function(){

    var $container = $('#container');

    $container.isotope({
      itemSelector: '.shifty-item',
      layoutMode: 'masonryColumnShift'
    });

    $container.find('.shifty-item').hover(
      function() {
        $(this).css({ height: "+=100" });
        // note that element is passed in, not jQuery object
        $container.isotope( 'shiftColumnOfItem', this );
      },
      function() {
        $(this).css({ height: "-=100" });
        $container.isotope( 'shiftColumnOfItem', this );
      }
    );

  });
</script>