CSS animated hexagon menu
Asked Answered
H

3

12

I'm trying to figure out the best way to build an animated hexagon menu. Please, see the following image for better understanding:

Animated hexagonal menu

The hexagon burger button is in the center. Once clicked, it reveals the triangular shapes surrounding the burger button. The latter transformed into a cross to reverse the process and hide everything back to the how it started.

My picture is actually missing one step in the very beginning. The first picture should only show the burger button just as the codepen demo.

So my question is the following :

Could you please me advise me on how you would build this hexagon menu animation from HTML to CSS through jQuery and others. What techniques would you use to make it happen. Keep in mind that whereas the codepen example is featuring simple icons, mine features triangular pictures which once hovered reveal a title with subtitle.

Hautboy answered 18/4, 2015 at 13:4 Comment(4)
If I had to fix this problem I propably used <svg> or <canvas> because you can easely draw triangular shapes, backgrounds and even animate them.Bedazzle
is there any code of yours to point you in a direction that fits your actual code ?Hepner
this might help: #23108146Speak
Right now I'm at the concept step where I'm thinking what to feature in this new website. So I had the idea of a hexagonal menu with triangles going out of it. At this point I've only drawn what I'd like to feature. I'm here to figure how to code this concept. @web-tiki: thanks for the link, I like this variant but that's not exactly what I want.Nonconformance
S
27

Here is an approach and demo for a

Hexagon menu demo

And here is an animated gif of the hexagon menu in action :

Hexagon menu with CSS HTML SVG ad JS

Hexagon menu main features :

  • responsive according to the viewport size (vmin). This can be modified by changing the width/height values to percentages (aspect ratio needs to be maintained see here)
  • Images (with the <img/> tag), titles and subtitles
  • 6 menu items
  • animated burger icon in a hexagon outline
  • menu item boundaries are clipped to triangles so they don't overlap each other. This way, the click event and hover state are triggered only when the actual menu item is hovered/clicked (except for IE, see browser support at the en of this post)
  • Can be featured over images, gradients or any non plain backgrounds

The hexagonal layout :

  • CSS3 2d transforms to make the triangles skewY() and rotate()
  • the menu items are clipped to triangles with .tr and .clip, unskewed with .clip and unrotated with .content the hexagon shape around the burger is made with an SVG polygon (easier to make and better result than with CSS (see 1st version)
  • The burger icon is made with a span and 2 pseudo elements

Hexagon menu featuring Animation :

  • the triangles are transitioned one by one (translate() and opacity) with the transition-delay property
  • the "bounce effect" for the triangle featuring animation is made with the transition-timming-function and a cubic bezier curve
  • the burger to cross animation is made by transitioning the 2 pseudo elments (translate() and rotate()) and fading the center elements background to a transparent rgba color

Hover animations :

  • the burger hexagon hover effect is made by animating the stroke-dashoffset property of the SVG <polygon> element.
  • the menu item titles and subtitles are featured on hover using 3D transforms (translateZ()) and opacity. The images are faded out at the same time

Used technology :

  • the CSS is coded with the help of SCSS and Autoprefixer to make it easier to write, read and shorter. You can see the compiled CSS by clicking on the "view compiled" button in the demo (the compiled CSS is also available at the end of this post)
  • SVG for the hexagon around the burger
  • HTML for the markup
  • plain JS to trigger the featuring animation with a class change on the container

Browser support :

I tested this menu on IE 11, chrome, FF and opera on a windows system. and the menu works on all these browsers. Chrome and FF render the font with blur (as seen in the animated gif made with chrome) and FF tends to make jagged sides for the triangles.

IE 11 has the best quality output for the fonts and triangles but :

  • it doesn't support SMIL animations and therefore doesn't render the hover effect on the burger hexagon
  • the overflow property for the links is ignored and the boundaries of the triangles aren't maintained

I used crossbrowser testing to test safari support and the hexagon menu works on that system too.


For people who got this far, here is another link to the demo : hexagon menu
And the full code with the compiled CSS :

var hexNav = document.getElementById('hexNav');

document.getElementById('menuBtn').onclick = function() {
    var className = ' ' + hexNav.className + ' ';
    if ( ~className.indexOf(' active ') ) {
        hexNav.className = className.replace(' active ', ' ');
    } else {
        hexNav.className += ' active';
    }              
}
* {
  margin: 0;
  padding: 0;
}

html, body {
  height: 100%;
}

body {
  font-family: 'Open Sans', sans-serif;
  background: #E3DFD2;
}

ul {
  list-style-type: none;
}

a, a:hover, a:focus, a:visited {
  text-decoration: none;
}

nav {
  position: relative;
  width: 70vmin;
  height: 70vmin;
  min-width: 500px;
  min-height: 500px;
  margin: 0 auto;
  overflow: hidden;
}

/** MENU BUTTON ******************************************/
#menuBtn {
  position: absolute;
  top: 45%;
  left: 45%;
  width: 10%;
  height: 10%;
  cursor: pointer;
  z-index: 2;
  will-change: transform;
}
#menuBtn svg {
  display: block;
}
#menuBtn:hover svg polygon {
  -webkit-animation: hexHover 0.7s;
          animation: hexHover 0.7s;
}
#menuBtn span {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 2px;
  padding: 8px 0;
  background-clip: content-box;
  background-color: #585247;
  -webkit-transform: translate(-50%, -50%);
      -ms-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
  -webkit-transition: background-color 0.5s;
          transition: background-color 0.5s;
}
#menuBtn span:before, #menuBtn span:after {
  position: absolute;
  background-color: #585247;
  content: '';
  width: 20px;
  height: 2px;
  -webkit-transition: -webkit-transform 0.5s;
          transition: transform 0.5s;
}
#menuBtn span:before {
  top: 0;
}
#menuBtn span:after {
  bottom: 0px;
}

@-webkit-keyframes hexHover {
  0% {
    stroke-dasharray: 0,0,300;
  }
  10% {
    stroke-dasharray: 0,20,300;
  }
  100% {
    stroke-dasharray: 300,20,300;
  }
}

@keyframes hexHover {
  0% {
    stroke-dasharray: 0,0,300;
  }
  10% {
    stroke-dasharray: 0,20,300;
  }
  100% {
    stroke-dasharray: 300,20,300;
  }
}
/** MENU ITEMS *******************************************/
#hex {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  -webkit-transform: scale(0.1) translatez(0);
      -ms-transform: scale(0.1) translatez(0);
          transform: scale(0.1) translatez(0);
  -webkit-transition: -webkit-transform 0.05s 0.5s;
          transition: transform 0.05s 0.5s;
}

.tr {
  position: absolute;
  left: 50%;
  bottom: 50%;
  width: 34.6%;
  height: 40%;
  -webkit-transform-origin: 0 100%;
      -ms-transform-origin: 0 100%;
          transform-origin: 0 100%;
  overflow: hidden;
  -webkit-transform: skewY(-30deg);
      -ms-transform: skewY(-30deg);
          transform: skewY(-30deg);
  opacity: 0;
}

.tr:nth-child(1) {
  -webkit-transform: rotate(0deg) skewY(-30deg);
      -ms-transform: rotate(0deg) skewY(-30deg);
          transform: rotate(0deg) skewY(-30deg);
  -webkit-transition: opacity 0.5s, -webkit-transform 0.5s;
          transition: opacity 0.5s, transform 0.5s;
}
.tr:nth-child(1) .clip {
  -webkit-transform: skewY(30deg) rotate(30deg);
      -ms-transform: skewY(30deg) rotate(30deg);
          transform: skewY(30deg) rotate(30deg);
}
.tr:nth-child(1) .content {
  -webkit-transform: rotate(-30deg);
      -ms-transform: rotate(-30deg);
          transform: rotate(-30deg);
  -webkit-transform-origin: 0 0;
      -ms-transform-origin: 0 0;
          transform-origin: 0 0;
  padding-left: 15%;
  -webkit-perspective-origin: 30% 70%;
          perspective-origin: 30% 70%;
}

.active .tr:nth-child(1) {
  -webkit-transform: rotate(0deg) skewY(-30deg) translate(10%, -10%);
      -ms-transform: rotate(0deg) skewY(-30deg) translate(10%, -10%);
          transform: rotate(0deg) skewY(-30deg) translate(10%, -10%);
  -webkit-transition: opacity 0.5s 0.05s, -webkit-transform 0.5s 0.05s cubic-bezier(0, 2.3, 0.8, 1);
          transition: opacity 0.5s 0.05s, transform 0.5s 0.05s cubic-bezier(0, 2.3, 0.8, 1);
}

.tr:nth-child(2) {
  -webkit-transform: rotate(60deg) skewY(-30deg);
      -ms-transform: rotate(60deg) skewY(-30deg);
          transform: rotate(60deg) skewY(-30deg);
  -webkit-transition: opacity 0.5s, -webkit-transform 0.5s;
          transition: opacity 0.5s, transform 0.5s;
}
.tr:nth-child(2) .clip {
  -webkit-transform: skewY(30deg) rotate(30deg);
      -ms-transform: skewY(30deg) rotate(30deg);
          transform: skewY(30deg) rotate(30deg);
}
.tr:nth-child(2) .content {
  -webkit-transform: rotate(-90deg);
      -ms-transform: rotate(-90deg);
          transform: rotate(-90deg);
  top: -8%;
  left: 6.67%;
  padding-left: 30%;
  -webkit-perspective-origin: 30% 50%;
          perspective-origin: 30% 50%;
}

.active .tr:nth-child(2) {
  -webkit-transform: rotate(60deg) skewY(-30deg) translate(10%, -10%);
      -ms-transform: rotate(60deg) skewY(-30deg) translate(10%, -10%);
          transform: rotate(60deg) skewY(-30deg) translate(10%, -10%);
  -webkit-transition: opacity 0.5s 0.1s, -webkit-transform 0.5s 0.1s cubic-bezier(0, 2.3, 0.8, 1);
          transition: opacity 0.5s 0.1s, transform 0.5s 0.1s cubic-bezier(0, 2.3, 0.8, 1);
}

.tr:nth-child(3) {
  -webkit-transform: rotate(120deg) skewY(-30deg);
      -ms-transform: rotate(120deg) skewY(-30deg);
          transform: rotate(120deg) skewY(-30deg);
  -webkit-transition: opacity 0.5s, -webkit-transform 0.5s;
          transition: opacity 0.5s, transform 0.5s;
}
.tr:nth-child(3) .clip {
  -webkit-transform: skewY(30deg) rotate(30deg);
      -ms-transform: skewY(30deg) rotate(30deg);
          transform: skewY(30deg) rotate(30deg);
}
.tr:nth-child(3) .content {
  -webkit-transform: rotate(-150deg);
      -ms-transform: rotate(-150deg);
          transform: rotate(-150deg);
  -webkit-transform-origin: 42.3% 36.5%;
      -ms-transform-origin: 42.3% 36.5%;
          transform-origin: 42.3% 36.5%;
  padding-left: 10%;
  -webkit-perspective-origin: 30% 30%;
          perspective-origin: 30% 30%;
}

.active .tr:nth-child(3) {
  -webkit-transform: rotate(120deg) skewY(-30deg) translate(10%, -10%);
      -ms-transform: rotate(120deg) skewY(-30deg) translate(10%, -10%);
          transform: rotate(120deg) skewY(-30deg) translate(10%, -10%);
  -webkit-transition: opacity 0.5s 0.15s, -webkit-transform 0.5s 0.15s cubic-bezier(0, 2.3, 0.8, 1);
          transition: opacity 0.5s 0.15s, transform 0.5s 0.15s cubic-bezier(0, 2.3, 0.8, 1);
}

.tr:nth-child(4) {
  -webkit-transform: rotate(180deg) skewY(-30deg);
      -ms-transform: rotate(180deg) skewY(-30deg);
          transform: rotate(180deg) skewY(-30deg);
  -webkit-transition: opacity 0.5s, -webkit-transform 0.5s;
          transition: opacity 0.5s, transform 0.5s;
}
.tr:nth-child(4) .clip {
  -webkit-transform: skewY(30deg) rotate(30deg);
      -ms-transform: skewY(30deg) rotate(30deg);
          transform: skewY(30deg) rotate(30deg);
}
.tr:nth-child(4) .content {
  -webkit-transform: rotate(-210deg);
      -ms-transform: rotate(-210deg);
          transform: rotate(-210deg);
  -webkit-transform-origin: 65.4% 38.4%;
      -ms-transform-origin: 65.4% 38.4%;
          transform-origin: 65.4% 38.4%;
  padding-left: 30%;
  -webkit-perspective-origin: 70% 30%;
          perspective-origin: 70% 30%;
}

.active .tr:nth-child(4) {
  -webkit-transform: rotate(180deg) skewY(-30deg) translate(10%, -10%);
      -ms-transform: rotate(180deg) skewY(-30deg) translate(10%, -10%);
          transform: rotate(180deg) skewY(-30deg) translate(10%, -10%);
  -webkit-transition: opacity 0.5s 0.2s, -webkit-transform 0.5s 0.2s cubic-bezier(0, 2.3, 0.8, 1);
          transition: opacity 0.5s 0.2s, transform 0.5s 0.2s cubic-bezier(0, 2.3, 0.8, 1);
}

.tr:nth-child(5) {
  -webkit-transform: rotate(240deg) skewY(-30deg);
      -ms-transform: rotate(240deg) skewY(-30deg);
          transform: rotate(240deg) skewY(-30deg);
  -webkit-transition: opacity 0.5s, -webkit-transform 0.5s;
          transition: opacity 0.5s, transform 0.5s;
}
.tr:nth-child(5) .clip {
  -webkit-transform: skewY(30deg) rotate(30deg);
      -ms-transform: skewY(30deg) rotate(30deg);
          transform: skewY(30deg) rotate(30deg);
}
.tr:nth-child(5) .content {
  -webkit-transform: rotate(-270deg);
      -ms-transform: rotate(-270deg);
          transform: rotate(-270deg);
  top: -8%;
  left: 6.67%;
  padding-left: 15%;
  -webkit-perspective-origin: 70% 50%;
          perspective-origin: 70% 50%;
}

.active .tr:nth-child(5) {
  -webkit-transform: rotate(240deg) skewY(-30deg) translate(10%, -10%);
      -ms-transform: rotate(240deg) skewY(-30deg) translate(10%, -10%);
          transform: rotate(240deg) skewY(-30deg) translate(10%, -10%);
  -webkit-transition: opacity 0.5s 0.25s, -webkit-transform 0.5s 0.25s cubic-bezier(0, 2.3, 0.8, 1);
          transition: opacity 0.5s 0.25s, transform 0.5s 0.25s cubic-bezier(0, 2.3, 0.8, 1);
}

.tr:nth-child(6) {
  -webkit-transform: rotate(300deg) skewY(-30deg);
      -ms-transform: rotate(300deg) skewY(-30deg);
          transform: rotate(300deg) skewY(-30deg);
  -webkit-transition: opacity 0.5s, -webkit-transform 0.5s;
          transition: opacity 0.5s, transform 0.5s;
}
.tr:nth-child(6) .clip {
  -webkit-transform: skewY(30deg) rotate(30deg);
      -ms-transform: skewY(30deg) rotate(30deg);
          transform: skewY(30deg) rotate(30deg);
}
.tr:nth-child(6) .content {
  -webkit-transform: rotate(-330deg);
      -ms-transform: rotate(-330deg);
          transform: rotate(-330deg);
  -webkit-transform-origin: 106.7% 25.2%;
      -ms-transform-origin: 106.7% 25.2%;
          transform-origin: 106.7% 25.2%;
  padding-left: 30%;
  -webkit-perspective-origin: 70% 70%;
          perspective-origin: 70% 70%;
}

.active .tr:nth-child(6) {
  -webkit-transform: rotate(300deg) skewY(-30deg) translate(10%, -10%);
      -ms-transform: rotate(300deg) skewY(-30deg) translate(10%, -10%);
          transform: rotate(300deg) skewY(-30deg) translate(10%, -10%);
  -webkit-transition: opacity 0.5s 0.3s, -webkit-transform 0.5s 0.3s cubic-bezier(0, 2.3, 0.8, 1);
          transition: opacity 0.5s 0.3s, transform 0.5s 0.3s cubic-bezier(0, 2.3, 0.8, 1);
}

.tr:nth-child(7) {
  -webkit-transform: rotate(360deg) skewY(-30deg);
      -ms-transform: rotate(360deg) skewY(-30deg);
          transform: rotate(360deg) skewY(-30deg);
  -webkit-transition: opacity 0.5s, -webkit-transform 0.5s;
          transition: opacity 0.5s, transform 0.5s;
}
.tr:nth-child(7) .clip {
  -webkit-transform: skewY(30deg) rotate(30deg);
      -ms-transform: skewY(30deg) rotate(30deg);
          transform: skewY(30deg) rotate(30deg);
}
.tr:nth-child(7) .content {
  -webkit-transform: rotate(-390deg);
      -ms-transform: rotate(-390deg);
          transform: rotate(-390deg);
}

.active .tr:nth-child(7) {
  -webkit-transform: rotate(360deg) skewY(-30deg) translate(10%, -10%);
      -ms-transform: rotate(360deg) skewY(-30deg) translate(10%, -10%);
          transform: rotate(360deg) skewY(-30deg) translate(10%, -10%);
  -webkit-transition: opacity 0.5s 0.35s, -webkit-transform 0.5s 0.35s cubic-bezier(0, 2.3, 0.8, 1);
          transition: opacity 0.5s 0.35s, transform 0.5s 0.35s cubic-bezier(0, 2.3, 0.8, 1);
}

.clip {
  position: absolute;
  top: 0;
  left: 0;
  width: 116%;
  height: 86.66%;
  overflow: hidden;
  -webkit-transform-origin: 0 0;
      -ms-transform-origin: 0 0;
          transform-origin: 0 0;
}

.content {
  position: absolute;
  width: 86.6%;
  height: 116%;
  top: 0;
  left: 0;
  box-sizing: border-box;
  font-size: 2vmin;
  -webkit-perspective: 500px;
          perspective: 500px;
  background: #000;
}
.content img {
  position: absolute;
  top: 0;
  left: -50%;
  right: -50%;
  margin: auto;
  height: 100%;
  z-index: -1;
  -webkit-transition: opacity 0.3s;
          transition: opacity 0.3s;
  pointer-events: none;
}
.content h2, .content p {
  position: absolute;
  width: 60%;
  line-height: 1em;
  color: #fff;
  opacity: 0;
  -webkit-transform: translateZ(-50px);
          transform: translateZ(-50px);
}
.content h2 {
  bottom: 50%;
  text-transform: uppercase;
  font-weight: 900;
  font-size: 2em;
  -webkit-transition: -webkit-transform 0.3s cubic-bezier(0, 2.3, 0.8, 1), opacity 0.3s;
          transition: transform 0.3s cubic-bezier(0, 2.3, 0.8, 1), opacity 0.3s;
}
.content p {
  position: absolute;
  top: 50%;
  font-size: 1em;
  -webkit-transition: -webkit-transform 0.3s 0.075s cubic-bezier(0, 2.3, 0.8, 1), opacity 0.3s 0.075s;
          transition: transform 0.3s 0.075s cubic-bezier(0, 2.3, 0.8, 1), opacity 0.3s 0.075s;
}
.content:hover h2, .content:hover p {
  opacity: 1;
  -webkit-transform: translatez(0);
      -ms-transform: translatez(0);
          transform: translatez(0);
}
.content:hover img {
  opacity: 0.4;
}

.active #menuBtn:hover svg polygon {
  -webkit-animation: none;
          animation: none;
}
.active #menuBtn span {
  background-color: transparent;
}
.active #menuBtn span:before {
  -webkit-transform: translatey(8px) rotate(45deg);
      -ms-transform: translatey(8px) rotate(45deg);
          transform: translatey(8px) rotate(45deg);
}
.active #menuBtn span:after {
  -webkit-transform: translatey(-8px) rotate(-45deg);
      -ms-transform: translatey(-8px) rotate(-45deg);
          transform: translatey(-8px) rotate(-45deg);
}
.active #hex {
  -webkit-transform: scale(0.9) translatez(0);
      -ms-transform: scale(0.9) translatez(0);
          transform: scale(0.9) translatez(0);
  -webkit-transition: none;
          transition: none;
  will-change: transform;
}
.active .tr {
  opacity: 1;
  will-change: transform;
}
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,800' rel='stylesheet' type='text/css'>
<nav id="hexNav">
  <div id="menuBtn">
    <svg viewbox="0 0 100 100">
      <polygon points="50 2 7 26 7 74 50 98 93 74 93 26" fill="none" stroke-width="4" stroke="#585247" stroke-dasharray="0,0,300"/>
    </svg>
    <span></span>
  </div>
  <ul id="hex">
    <li class="tr"><div class="clip"><a href="#" class="content">
      <img src="https://farm8.staticflickr.com/7435/13629508935_62a5ddf8ec_c.jpg" alt="" />
      <h2 class="title">Title</h2><p>Catch phrase</p>
    </a></div></li>
    <li class="tr"><div class="clip"><a href="#" class="content">
      <img src="https://farm3.staticflickr.com/2827/10384422264_d9c7299146.jpg" alt="" />
      <h2 class="title">Title</h2><p>Catch phrase</p>
    </a></div></li>
    <li class="tr"><div class="clip"><a href="#" class="content">
      <img src="https://farm7.staticflickr.com/6083/6055581292_d94c2d90e3.jpg" alt="" />
      <h2 class="title">Title</h2><p>Catch phrase</p>
    </a></div></li>
    <li class="tr"><div class="clip"><a href="#" class="content">
      <img src="https://farm7.staticflickr.com/6092/6227418584_d5883b0948.jpg" alt="" />
      <h2 class="title">Title</h2><p>Catch phrase</p>
    </a></div></li>
    <li class="tr"><div class="clip"><a href="#" class="content">
      <img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" alt="" />
      <h2 class="title">Title</h2><p>Catch phrase</p>
    </a></div></li>
    <li class="tr"><div class="clip"><a href="#" class="content">
      <img src="https://farm4.staticflickr.com/3766/12953056854_b8cdf14f21.jpg" alt="" />
      <h2 class="title">Title</h2><p>Catch phrase</p>
    </a></div></li>
  </ul>
</nav>

Here is a link to the : first version

Speak answered 18/4, 2015 at 18:44 Comment(8)
Awesome web-tiki! That's exactly what I was talking about! Thanks so much for sharing this nice menu. I tried it in Firefox and it seems that there is a triangle within the hexagon in the idle position. It's not a big deal but in Chrome it doesn't show up. Also the triangles even though they're invisible are still there, the mouse pointer still detects them. I think modifying the DOM with some javascript in there will do the trick to clean it up and make it crossbrowser. What do you guys think?Nonconformance
@JulianLivin'inChina glad you like it. This definetly need some more crossbrowser testing. I went for a CSS only approach (and different to the one I linked earlier) but JS would allow to hide the elements totaly. There also seems to be issues in IE with overlapping elements. Now I remember why I use the other approach in the other question. I will try to update this to make it more crossbrowser and usable in real life with shorter code but I won't have time right now. I also have some ideas for the animation which I will try to get together.Speak
@web-tiki: if you take more time improving it, I hope at least it will be useful for others as well so your time can be well spent. Anyhow, I love it and I'll definitely try to implement in my actual project.Nonconformance
@web-tiki: Man, that awesome! How kind of you to take the time to build such a challenging animation. Thank you so much for your work!Nonconformance
After many days I revisited the answer and I'm glad I did. I do apreciate all the little details (that sadly many people won't even notice) in your work. TYShlomo
Thank you for that nice comment @AlvaroMenéndez and glad you like this hexagon menu. It was fun to make :)Speak
Totally agree with Alvaro's last comment. You've done such an amazing work using clean code and best practise, hats off. I'm a novice at javascript which I'm currently learning, I'll figure out your code later luckily it's short :). However I didn't upgrade my HTML5 and CSS3 since its beginning. I know it's a shame so I'm going to take care of it. Do you guys recommend any course or tutorial I could follow in order to be able to comprehend the above codes? Thanks again for this awesome menu. I forgot to ask, did you build the svg hexagon using an online generator or you made it line by line?Nonconformance
@JulianLivin'inChina come and chat here it will be easier to explain :)Speak
H
5

Ok. I have made a fiddle fo you because it was fun and nice practise (and something I will keep for any future necesity) and because you may use it to achieve what you want.

First the HTML which is quite basic:

<div class="container">
    <div class="shape x1"></div>
    <div class="shape x2"></div>
    <div class="shape x3"></div>
    <div class="shape x4"></div>
    <div class="shape x5"></div>
    <div class="shape x6"></div>
    <div class="button">X</a>
</div>

and easy to understand. Basically on a relative container You place your triangles (one each div) with position absolute.

I have used css shapes for the triangles but I DO recomend for your example, specially as you may use images inside the shapes to better use plain images with transparent background on a normal shape div. then position the elements till you get what you want.

so I have use the comun class shape to get the comon css properties:

shape {
    width: 0;
    height: 0;
    border-left: 58px solid transparent;
    border-right: 58px solid transparent;
    border-bottom: 100px solid red;
    position:absolute;
    transform-origin: center;
}

and then the "x" classes to position the elements in place as this one:

.x1 {
    transform: rotate(90deg);
    left:0;
    top:50px;    
}

If You use triangular images, obviously you ignore the rotation.

and I've placed the button in the middle.

Then it's time for this very simple jquery:

$(document).ready(function () {
            $('.button').click(function () {
                $('.x1').toggleClass("trans1");
                $('.x2').toggleClass("trans2");
                $('.x3').toggleClass("trans3");
                $('.x4').toggleClass("trans4");
                $('.x5').toggleClass("trans5");
                $('.x6').toggleClass("trans6");
                $('.button').toggleClass("button2")

            });
        });  

which basically adds and removes a class to every element when you click the button.

Now you just have to use the new classes to reposition the elements and create the effect you want... use the button new class to (for example) change the background image of your button (burger for cross) and just add a simple transition like:

transition: all 1s linear;

Here you have the FIDDLE. I hope this could help you in your project.

Edited: If you want your elements to "close" with transition, add the property to the original classes and not to one created by the jquery. (I just like it better as now)

Housecoat answered 18/4, 2015 at 15:36 Comment(6)
Sorry Alvaro but there are 2 major flaws with this: the elements are overlapping each other (and therefore the click area as well) and you can't apply a background image on a border.Cloudburst
Sorry mack but as I clearly say in the answer this is basically to show how to make the animations and I clearly suggested to make the shapes as images with background transparent, or even better but much more complicated for people just starting, to use svg. Anyway ty for your downvote (which actually is when an answer is NOT useful). If you think that way it's fine with meShlomo
The answer is not useful at all because it throws off completely somebody trying to solve this very problem following your answer therefore generating even way more problems. As I said the click areas would overlap and also having a transparent triangular image doesn't allow you to have title and subtitle inside the triangular element itself as it has been asked in the last paragraph of this question. (Unless using another hover image, which is awful because you can't use then CSS3 effects on hover, very bad for SEO, and extremely bad if you want to change text/typos/rearrange the menu)Cloudburst
To continue: I think the animation itself is lovely and I recognize that you are rendering on the screen an element which is 100% cross-browser compatible, but lets put it in that way: he asked for a pizza and you gave him a cake. While it has the same shape you can't put tomato sauce and salami in the cake, and all the people coming after him will follow your recipe thinking they will get a pizza but they will end up with a cake with a really odd taste.Cloudburst
Thanks man, that's a nice variant! I understand what Alvaro is saying. I have to be able to put pictures with title + subtitle within each triangle. Web-tiki did a good job at implementing all this. However, it is not completely cross-browser because it uses pure CSS whereas in your case it uses java-script which I'd rather use.Nonconformance
Nice to know that the op doesn't think my answer is "not usefull at all". not like other people who still try to justified the "fast triggered" downvotes with some detail explanation as why an answer is NOT the perfect one (while, of course, not providing any solutions by themselves)Shlomo
F
0

Hope this helps someone Here's a codepen with a working example. https://codepen.io/jaygriggs/pen/zYpaKBY


nav {
  position: relative;
  width: 70vmin;
  height: 70vmin;
  min-width: 500px;
  min-height: 500px;
  margin: 0 auto;
  overflow: hidden;
}

/** MENU BUTTON ******************************************/
#menuBtn {
  position: absolute;
  top: 45%;
  left: 45%;
  width: 10%;
  height: 10%;
  z-index: 2;
  
}
#menuBtn svg {
  display: block;
}
#menuBtn svg polygon:hover {
  -webkit-animation: hexHover 0.7s;
          animation: hexHover 0.7s;
  cursor: pointer;
}
#menuBtn span {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 2px;
  padding: 8px 0;
  background-clip: content-box;
  background-color: #585247;
  transform: translate(-50%, -50%);
  transition: background-color 0.3s;
  pointer-events: none;
}
#menuBtn span:before, #menuBtn span:after {
  position: absolute;
  background-color: #585247;
  content: '';
  width: 20px;
  height: 2px;
  transition: transform 0.3s;
}
#menuBtn span:before {
  top: 0;
}
#menuBtn span:after {
  bottom: 0px;
}
Fielder answered 10/4, 2022 at 0:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.