How to make menu fold like paper using CSS?


Tags: html,css,css3,css-transitions,css-transforms

Problem :

I wish to make a navigational menu that unfolds like paper using CSS only, looking like something like this: http://felixniklas.com/paperfold/ since it's mostly using CSS to create the transition effect.

Unfortunately the effect I get is still not as good, it's like this: https://jsfiddle.net/yaharga/7z2rg8gk/. There are spaces showing and the li don't stick together. Ideally I'd like to make the effect show on submenus as well.

I summarized the code to show the transition and transformation css involved:

// Nav Button Toggle
jQuery('.dropdown-toggle').on('click', function() {
  jQuery(this).toggleClass('active');
});
.dropdown-toggle {
  color: #ecf0f1;
  padding: 12px 0;
}

.dropdown-toggle.acitve {
  color: #bdc3c7
}

.toggleable {
  -webkit-transition: max-height .75s ease-in-out, -webkit-transform .75s ease-in-out, visibility .75s ease-in-out;
  transition: max-height .75s ease-in-out, transform .75s ease-in-out, visibility .75s ease-in-out;
  -webkit-transform-origin: top;
  transform-origin: top;
  -webkit-perspective: 320px;
  perspective: 320px;
  -webkit-transform: scaleY(0);
  transform: scaleY(0);
  list-style: none;
  position: relative;
  margin: 0;
  padding: 0
}

.dropdown-toggle.active+.toggleable {
  visibility: visible;
  max-height: 1200px;
  -webkit-transform: scaleY(1);
  transform: scaleY(1)
}

.nav-primary {
  margin: 30px 10px;
  text-align: center;
  position: relative
}

#menu-main-toggle {
  border: 0;
  background-color: #e74c3c;
  width: 100%;
  border-bottom: 1px dashed #c0392b;
}

#menu-main {
  width: 100%;
  position: absolute
}

#menu-main,
.toggleable {
  position: relative
}

.dropdown-toggle,
.menu-item {
  background: #e74c3c
}

.menu-item {
  border-top: 1px dashed #c0392b;
  transition: transform .75s ease-in-out;
}

.dropdown-toggle.active + #menu-main .menu-item {
  transform: rotateX(0deg);
}

.odd {
  transform: rotateX(-90deg);
}

.even {
  transform: rotateX(90deg);
}

.menu-item.first {
  border-top: none
}

.menu-link {
  display: block;
  padding: 12px 0;
  color: #ecf0f1
}

.menu-link:active {
  color: #fbfcfc
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<nav class="nav-primary">
  <button id="menu-main-toggle" class="dropdown-toggle">Menu</button>
  <ul id="menu-main" class="nav toggleable hide">
    <li class="odd first menu-item"><a class="menu-link" href="//localhost:3000/index.php/about/">About</a></li>
    <li class="even menu-item"><a class="menu-link" href="/index.php/category/bahrain/">Bahrain</a></li>
    <li class="odd menu-item parent"><a class="menu-link" href="/index.php/category/information-technology/">Information Technology</a>
    </li>
    <li class="even menu-item"><a class="menu-link" href="/index.php/category/snippets/">Snippets</a></li>
    <li class="odd last menu-item"><a class="menu-link" href="//localhost:3000/index.php/contact/">Contact</a></li>
  </ul>
</nav>



Solution :

I solved it by using a negative margin and transitioning that with the same amount of time it takes for the transformation to transition (credit for solution goes to @GCyrillus's codepen). I set the margins as double the size of the menu items as margins collapse so it was perfect. It's the closest I could get to the desired effect, though I would have prefered to get the effect of Felix Niklas's plugin. I think it uses shadows as well, but that cannot be implemented with pure CSS as transitions are linear.

You may correct me on any of which I have said or add to my code.

// Nav Button Toggle
jQuery('.dropdown-toggle').on('click', function() {
  jQuery(this).toggleClass('active');
});
.dropdown-toggle {
  color: #ecf0f1;
  padding: 12px 0;
}

.dropdown-toggle.acitve {
  color: #bdc3c7
}

.toggleable {
  -webkit-transition: max-height .75s ease-in-out, -webkit-transform .75s ease-in-out, visibility .75s ease-in-out;
  transition: max-height .75s ease-in-out, transform .75s ease-in-out, visibility .75s ease-in-out;
  -webkit-transform-origin: top;
  transform-origin: top;
  -webkit-transform: scaleY(0);
  transform: scaleY(0);
  list-style: none;
  position: relative;
  margin: 0;
  padding: 0
}

.toggleable .toggleable {
  -webkit-transform-origin: center;
  transform-origin: center;
}

.dropdown-toggle.active+.toggleable {
  visibility: visible;
  max-height: 1200px;
  -webkit-transform: scaleY(1);
  transform: scaleY(1)
}

#nav-primary {
  margin: 30px 10px;
  text-align: center;
  position: relative
}

#menu-main-toggle {
  border: 0;
  background-color: #e74c3c;
  width: 100%;
  border-bottom: 1px dashed #c0392b;
  height: 50px;
}

#menu-main {
  width: 100%;
  position: absolute
}

.dropdown-toggle,
.menu-item {
  background: #e74c3c
}

.menu-item {
  border-top: 1px dashed #c0392b;
  height: 50px;
  transition: transform .75s ease-in-out, margin .75s ease-in-out;
}

#menu-main .menu-item.odd {
  -webkit-transform: perspective(320px) rotateX(90deg);
  transform: perspective(320px) rotateX(90deg);
  -webkit-transform-origin: bottom;
  transform-origin: bottom;
  margin-top: -100px
}
#menu-main .menu-item.even {
  -webkit-transform: perspective(320px) rotateX(-90deg);
  transform: perspective(320px) rotateX(-90deg);
  -webkit-transform-origin: top;
  transform-origin: top;
  margin-bottom: -100px
}

#nav-primary .dropdown-toggle.active + .toggleable .menu-item {
  -webkit-transform: perspective(320px) rotateX(0deg);
  transform: perspective(320px) rotateX(0deg);
  margin: 0
}

.menu-item.first {
  border-top: none
}

.menu-link {
  display: block;
  padding: 12px;
  color: #ecf0f1
}

.menu-link:active {
  color: #fbfcfc
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<nav id="nav-primary">
  <button id="menu-main-toggle" class="dropdown-toggle">Menu</button>
  <ul id="menu-main" class="nav toggleable hide">
    <li class="odd first menu-item"><a class="menu-link" href="//localhost:3000/index.php/about/">About</a></li>
    <li class="even menu-item"><a class="menu-link" href="/index.php/category/bahrain/">Bahrain</a></li>
    <li class="odd menu-item parent"><a class="menu-link" href="/index.php/category/information-technology/">Information Technology</a>
    </li>
    <li class="even menu-item"><a class="menu-link" href="/index.php/category/snippets/">Snippets</a></li>
    <li class="odd last menu-item"><a class="menu-link" href="//localhost:3000/index.php/contact/">Contact</a></li>
  </ul>
</nav>

Edit: For all those interested, I completed the effect using box-shadowing here: http://stackoverflow.com/a/38083570/1934402.


    CSS Howto..

    How to use a full width image as border between content and footer

    How can I add pictures to my web via CSS

    Footer Showing White Bar on only one page of website

    How to keep control-specific css with the control code (ASP.NET)

    How to I apply a style to only the first row (matching a class) of a table using pure css?

    How to create a rounded rectangle shape Css?

    How do I set a different background to current tab?

    How to Highlight a list item after user clicks on link

    How can I have a CSS hover affect a different tag?

    How to vertically align data in the center of a table cell in HTML?

    How does Outlook.com have the title text underlined?

    How to reduce my code in both jQuery and CSS

    How can I stop a text link to go up each time it is selected?

    how to ignore rewriting css file with .htaccess

    How can I make a div 100% of the browser window height, but with a top and bottom margin?

    How to make an image not overlap navigation bar in CSS/HTML [closed]

    How to add Get in Touch page in webpage? [closed]

    How can I create scrollable columns in Bootstrap?

    How to make a table with no cells-per-row defined only with CSS

    Mobile Toggle Menu - How to Push Content outside the view of the viewport?

    How to create a box with rounded corners at the top, but normal corners at the bottom?

    jquery .show() hides immediately

    Picture doesn't show up [closed]

    How to give different color to draghandle in RangeSlider

    How to get slanted borders in CSS

    How to turn on Visual Studio 2010 .css Intellisense on .less file

    How to implement z-index and overflow

    How to make this series of rules into a mixin?

    HTML/CSS/JAVASCRIPT : How to move an element and not show scrollbars

    How to change the css style for phone and desktop?