<div class="layout">
  <div class="hover">
    <div class="content">Item 1</div>
    <div class="overlay"></div>
  </div>
  <div class="hover">
    <div class="content">Item 2</div>
    <div class="overlay"></div>
  </div>
  <div class="hover">
    <div class="content">Item 3</div>
    <div class="overlay"></div>
  </div>
  <div class="hover">
    <div class="content">Item 4</div>
    <div class="overlay"></div>
  </div>
  <div class="hover">
    <div class="content">Item 5</div>
    <div class="overlay"></div>
  </div>
  <div class="hover">
    <div class="content">Item 6</div>
    <div class="overlay"></div>
  </div>
</div>
.hover {
  overflow: hidden;
  perspective: 400px;

  .overlay {
    transform: translate3d(0, -100%, 0);
    animation-duration: 0.6s;
    animation-fill-mode: forwards;
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }

  // ENTER
  &.mouseenter {
    &.top {
      perspective-origin: center top;
      .overlay {
        animation-name: swing--enter-top;
        transform-origin: center top;
      }
    }
    &.right {
      perspective-origin: right center;
      .overlay {
        animation-name: swing--enter-right;
        transform-origin: right center;
      }
    }
    &.bottom{
      perspective-origin: center bottom;
      .overlay {
        animation-name: swing--enter-bottom;
        transform-origin: center bottom;
      }
    }
    &.left {
      perspective-origin: left center;
      .overlay {
        animation-name: swing--enter-left;
        transform-origin: left center;
      }
    }
  }

  // LEAVE
  &.mouseleave {
    &.top {
      perspective-origin: center top;
      .overlay {
        animation-name: swing--leave-top;
        transform-origin: center top;
      }
    }
    &.right {
      perspective-origin: right center;
      .overlay {
        animation-name: swing--leave-right;
        transform-origin: right center;
      }
    }
    &.bottom {
      perspective-origin: center bottom;
      .overlay {
        animation-name: swing--leave-bottom;
        transform-origin: center bottom;
      }
    }
    &.left {
      perspective-origin: left center;
      .overlay {
        animation-name: swing--leave-left;
        transform-origin: left center;
      }
    }
  }
}

// ANIMATIONS
@keyframes swing--enter-top {
  0% { transform: rotate3d(-1, 0, 0, 90deg); }
  100% { transform: none; }
}
@keyframes swing--enter-right {
  0% { transform: rotate3d(0, -1, 0, 90deg); }
  100% { transform: none; }
}
@keyframes swing--enter-bottom {
  0% { transform: rotate3d(1, 0, 0, 90deg); }
  100% { transform: none; }
}
@keyframes swing--enter-left {
  0% { transform: rotate3d(0, 1, 0, 90deg); }
  100% { transform: none; }
}
@keyframes swing--leave-top {
  0% { transform: none; }
  100% { transform: rotate3d(-1, 0, 0, 90deg); }
}
@keyframes swing--leave-right {
  0% { transform: none; }
  100% { transform: rotate3d(0, -1, 0, 90deg); }
}
@keyframes swing--leave-bottom {
  0% { transform: none; }
  100% { transform: rotate3d(1, 0, 0, 90deg); }
}
@keyframes swing--leave-left {
  0% { transform: none; }
  100% { transform: rotate3d(0, 1, 0, 90deg); }
}


/**
 * BASIC CSS FOR DEMO PURPOSE
 */
body {
  font-family: system-ui;
  background: #f06d06;
  color: white;
  text-align: center;
}
.layout {
  width: 800px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}

.hover {
  background-color: #4472C4;
  position: relative;
  display: flex;
  flex: 1 1 30%;
  margin: 1%;
  height: 150px;
  align-items: center;
  justify-items: center;
}

.content {
  flex: 1;
  text-align: center;
  line-height: 150px;
}

.overlay {
  position: absolute;
  height: 100%;
  width: 100%;
  background-color: #f08080;
  text-align: center;
}
View Compiled
/*
 * Get the direction by which an element as been hovered.
 *
 * It is done by determining in which quadrant is the mouse
 * inside the element when mouseenter/mouseleave event starts.
 * This is done using trigonometry on the pointer position
 * relative to the center of the element.
 * @see https://freelance-drupal.com/node/79 for details
 *
 * @param event
 *   The event triggering the computation.
 *
 * @result string
 *   Can be 'top', 'right', 'bottom', 'left' depending on the situation.
 */
const getHoverDirection = function (event) {
  var directions = ['top', 'right', 'bottom', 'left'];
  var item = event.currentTarget;

  // Width and height of current item
  var w = item.offsetWidth;
  var h = item.offsetHeight;

  // Calculate the x/y value of the pointer entering/exiting, relative to the center of the item.
  // Scale (sort of normalize) the coordinate on smallest side to the scale of the longest.
  var x = (event.clientX - item.getBoundingClientRect().left - (w / 2)) * (w > h ? (h / w) : 1);
  var y = (event.clientY - item.getBoundingClientRect().top - (h / 2)) * (h > w ? (w / h) : 1);

  // Calculate the angle to the center the pointer entered/exited
  // and convert to clockwise format (top/right/bottom/left = 0/1/2/3).
  var d = Math.round(Math.atan2(y, x) / 1.57079633 + 5) % 4;

  return directions[d];
};

document.addEventListener('DOMContentLoaded', function (event) {
  // Loop over items (in a IE11 compatible way).
  var items = document.getElementsByClassName('hover');
  for (var i = 0; i < items.length; i++) {

    // Loop over the registered event types.
    ['mouseenter', 'mouseleave'].forEach(function (eventname) {
      items[i].addEventListener(eventname, function (event) {

        // Retrieve the direction of the enter/leave event.
        var dir = getHoverDirection(event);

        // Reset classes.
        // event.currentTarget.className = 'item hover';
        // > If support for IE11 is not needed.
        // event.currentTarget.classList.remove('mouseenter', 'mouseleave', 'top', 'right', 'bottom', 'left');
        // > If support for IE11 is needed.
        event.currentTarget.classList.remove('mouseenter');
        event.currentTarget.classList.remove('mouseleave');
        event.currentTarget.classList.remove('top');
        event.currentTarget.classList.remove('right');
        event.currentTarget.classList.remove('bottom');
        event.currentTarget.classList.remove('left');

        // Add the event and direction classes.
        // > If support for IE11 is not needed.
        // event.currentTarget.classList.add(event.type, dir);
        // > If support for IE11 is needed.
        event.currentTarget.className += ' ' + event.type + ' ' + dir;

      }, false);
    });
  }
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.