Dropdown Menu With Folding/Unfolding Effects

File Size: 6.04 KB
Views Total: 1288
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Dropdown Menu With Folding/Unfolding Effects

An experimental jQuery script to create a dropdown menu that allows the user to reveal menu items with folding/unfolding effects just like on a piece of paper.

How to use it:

1. Load the latest jQuery library and Bootstrap's stylesheet (for demo purpose) in the document.

<link rel="stylesheet" href="/path/to/cdn/bootstrap.min.css" />
<script src="/path/to/cdn/jquery.min.js"></script>

2. Create a dropdown menu using the Bootstrap's list group component as follows:

<ul class="list-group position-relative" id="foldingMenu">
  <li class="list-group-item d-flex align-items-center">
    <img class="mr-4" src="https://picsum.photos/100?random=1"/>
    <div>
      <h2>Lorem Ipsum 1</h2>
      <p>Dolor sit amet</p>
    </div>
  </li>
  <li class="list-group-item d-flex align-items-center">
    <img class="mr-4" src="https://picsum.photos/100?random=2"/>
    <div>
      <h2>Lorem Ipsum 2</h2>
      <p>Dolor sit amet</p>
    </div>
  </li>
  <li class="list-group-item d-flex align-items-center">
    <img class="mr-4" src="https://picsum.photos/100?random=3"/>
    <div>
      <h2>Lorem Ipsum 3</h2>
      <p>Dolor sit amet</p>
    </div>
  </li>
  ... more list items here ...
  <li class="list-group-item navbar-light text-center"><span class="navbar-toggler-icon"></span></li>
</ul>

3. The required CSS styles for the menu items.

.list-group li {
  position: absolute;
  left: 0px;
  right: 0px;
  zoom: 1;
  transform-origin: 50% 100%;
  transform: perspective(1000px) rotate3d(1, 0, 0, 90deg);
}

.list-group li:nth-child(even) {
  transform-origin: 50% 0%;
  background: #eee;
}

.list-group li:last-child {
  transform: none;
  cursor: pointer;
}

4. The main JavaScript (jQuery Script) to enable the folding dropdown menu.

const foldingMenu = $("#foldingMenu"),
  toggler = $("li:last-child", foldingMenu),
  steps = 10,
  animationTime = 400,
  perspective = 1000,
  degree = 90,
  classNames = {
    animatingUp: "animating-up",
    animatingDown: "animating-down",
    unfolded: "unfolded",
    folded: "folded"
  };
(() =>
 foldingMenu.each(() => {
  const evenChild = foldingMenu.children(":even").not(toggler),
        oddChild = foldingMenu.children(":odd").not(toggler),
        listItems = $('li', foldingMenu),
        firstItemHeight = $('li', foldingMenu).eq(0).outerHeight(),
        degreePerStep = degree / steps;
  let counter = 0;

  changeStatus = (callBack) => {
    (applyTransform = () => {
      let angle = 90 - (foldingMenu.hasClass(classNames.unfolded) ? --counter : ++counter) * degreePerStep,
          currentHeight = 0,
          itemTop = 0;
      evenChild.css("transform", `perspective(${perspective}px) rotate3d(1, 0, 0, -${angle}deg)`);
      oddChild.css("transform", `perspective(${perspective}px) rotate3d(1, 0, 0,${angle}deg)`);
      currentHeight = (counter >= 0) ? parseInt(listItems[0].getBoundingClientRect().height) : 0;
      for (let i = 0; i < listItems.length; i++) {
        itemTop = (1 === i % 2) ? currentHeight * (i + 1) - firstItemHeight : currentHeight * i;
        listItems[i].style.top = itemTop + "px";
      }
      (counter === steps || 0 === counter) ? callBack() : setTimeout(applyTransform, animationTime / steps);
    })();
  };
  toggler.on("click", e => {
    foldingMenu.hasClass(classNames.animatingUp) ||
      (foldingMenu.hasClass(classNames.unfolded) ? (foldingMenu.addClass(classNames.animatingUp),
          changeStatus(() => foldingMenu.removeClass(`${classNames.animatingUp} ${classNames.unfolded}`))
         )
       : (foldingMenu.addClass(classNames.animatingUp, classNames.animatingDown),
          changeStatus(() => {
      foldingMenu.removeClass(`${classNames.animatingUp} ${classNames.animatingDown}`);
      foldingMenu.addClass(classNames.unfolded);
    })));
    e.preventDefault();
  });
})
)(jQuery);

This awesome jQuery plugin is developed by housamz. For more Advanced Usages, please check the demo page or visit the official website.