1

Ì found a cool script to show a "rounded animated" hamburger menu, see https://jsfiddle.net/sigug/5ohmne6g/25/ I have a ul list of menu items, they currently don't show up because they are "display:none". When I remove that, they are just there (obviously). How do I show them now with the animated "circle" that popups up when clicking the menu? Since they are "outside" of the animation, is it only possible to fade them in "afterwards" or something?

HTML

<div class="menu"><button class="nav-tgl" type="button" aria-label="toggle menu"><span aria-hidden="true"></span></button>
    <nav class="nav">
        <ul>
            <li>element one</li>
            <li>element two</li>
            <li>element three</li>
            <li>element four</li>
        </ul>
    </nav>
</div>

CSS

.cd-nav-trigger {
  top: 18px;
  right: 5%;
  height: 44px;
  width: 44px;
  z-index: 5;
  /* image replacement */
  overflow: hidden;
  text-indent: 100%;
  white-space: nowrap;
}

.cd-overlay-nav, .cd-overlay-content {
  /* containers of the 2 main rounded backgrounds - these containers are used to position the rounded bgs behind the menu icon */
  position: fixed;
  top: 18px;
  right: 5%;
  height: 4px;
  width: 4px;
  transform: translateX(-20px) translateY(20px);
}

.cd-overlay-nav span, .cd-overlay-content span {
  display: inline-block;
  position: absolute;
  border-radius: 50%;
  will-change: transform;
  transform: scale(0);
}

.cd-nav-trigger .cd-icon {
  /* icon created in CSS */
  position: absolute;
  left: 50%;
  top: 50%;
  bottom: auto;
  right: auto;
  transform: translateX(-50%) translateY(-50%);
  display: inline-block;
  width: 18px;
  height: 3px;
  background-color: #ffffff;
  z-index: 10;
}

.cd-nav-trigger .cd-icon::before, .cd-nav-trigger .cd-icon:after {
  /* upper and lower lines of the menu icon */
  position: absolute;
  top: 0;
  right: 0;
  width: 100%;
  height: 100%;
  background-color: inherit;
  transition: transform .3s;
}

.cd-nav-trigger .cd-icon::before {
  transform: translateY(-6px) rotate(0deg);
}

.cd-nav-trigger .cd-icon::after {
  transform: translateY(6px) rotate(0deg);
}

.cd-nav-trigger.close-nav .cd-icon {
  /* user clicks on the .cd-nav-trigger element - transform the icon */
  background-color: rgba(255, 255, 255, 0);
}

.cd-nav-trigger.close-nav .cd-icon::before, .cd-nav-trigger.close-nav .cd-icon::after {
  background-color: white;
}

.cd-nav-trigger.close-nav .cd-icon::before {
  transform: translateY(0) rotate(45deg);
}

.cd-nav-trigger.close-nav .cd-icon::after {
  transform: translateY(0) rotate(-45deg);
}

.cd-nav-trigger::before, .cd-nav-trigger::after {
  /* 2 rounded colored backgrounds for the menu icon */
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  height: 100%;
  width: 100%;
  transition-property: transform;
}
.cd-nav-trigger::before {
  background-color: #091d23;
  transform: scale(1);
  transition-duration: 0.3s;
  transition-delay: 0.4s;
}
.cd-nav-trigger::after {
  background-color: #ffb441;
  transform: scale(0);
  transition-duration: 0s;
  transition-delay: 0s;
}
.cd-nav-trigger.close-nav::before {
  /* user clicks on the .cd-nav-trigger element - 1st rounded background disappears */
  transform: scale(0);
}
.cd-nav-trigger.close-nav::after {
  /* user clicks on the .cd-nav-trigger element - 2nd rounded background appears */
  transform: scale(1);
  transition-duration: 0.3s;
  transition-delay: 0.4s;
}

jQuery

const menu = document.querySelector('.menu');
const btn = menu.querySelector('.nav-tgl');
btn.addEventListener('click', evt => {
  menu.classList.toggle('active');
})
``
sigug
  • 1,159
  • 1
  • 11
  • 17
  • https://codyhouse.co/demo/rounded-animated-navigation/index.html#0 – Flash Thunder Jul 28 '20 at 07:46
  • Yeah, found that too. But it seems too old and much code (there is velocity.js used from 2014 - it doesn't work with latest version etc). Thanks though. – sigug Jul 28 '20 at 07:58

2 Answers2

1

You can use a seperate class that only contains the "display: none" and add it to the list at the start of your script. It's always easier to toggle classes that are not hardcoded to the element in HTML in my experience. Then you just select the Element with JQUERY and toggle the new class seperatly from the button menu, like this:

Jquery:

const menu = document.querySelector('.menu');
const btn = menu.querySelector('.nav-tgl');
$('.nav ul').addClass("hidden");
btn.addEventListener('click', evt => {
  menu.classList.toggle('active');
  $('.nav ul').toggleClass("hidden");
})

CSS:

.hidden {
  display: none;
}

JSfiddle

Warden330
  • 999
  • 1
  • 5
  • 11
  • Thanks, now the animation seems to be gone? – sigug Jul 28 '20 at 08:01
  • 1
    oh whoops, i didn't notice that sorry, i'll look into it – Warden330 Jul 28 '20 at 08:02
  • 1
    https://jsfiddle.net/b4e8z3ga/ here you go, added the property to the wrong Element, is that working for you? – Warden330 Jul 28 '20 at 08:10
  • oh wait your Question is not only about making the list apper, but make it appear smoothly with the button animation right? – Warden330 Jul 28 '20 at 08:25
  • Thank you! Yeah, that would be even better. And one more thing now would be: I'm a novice but now that nav menu would always show up when the user has no javascript enabled, since it's only hidden by js, right? Is there a way to fix that - sure the user can't use the menu anyway then, but it still would be better to not show it at least then... – sigug Jul 28 '20 at 08:32
  • 1
    https://jsfiddle.net/b4e8z3ga/2/ So css class is added directly in html, that prevents the NO-JS mistake and should still work. also added a seperate class with an animation that makes it appear way smoother. – Warden330 Jul 28 '20 at 08:37
1

Here is an all CSS solution. Instead of using an event, I used a checkbox with a label that acts as the button.

HTML

<div class="nav">
    <input type="checkbox" class="nav__checkbox" id="nav-toggle">
    <label for="nav-toggle" class="nav__button">
      <span class="nav__icon"></span>
    </label>

    <div class="nav__background"></div>

    <nav class="nav__menu">
        <ul class="nav__list">
            <li class="nav__item">Item1</li>
            <li class="nav__item">Item2</li>
            <li class="nav__item">Item3</li>
            <li class="nav__item">Item4</li>
        </ul>
    </nav>
</div>

CSS

.nav__checkbox{
  display: none;
}

.nav__button{
  background-color: #fff;
  position: fixed;
  height: 4.375rem;
  width: 4.375rem;
  border-radius: 50%;
  top: 2.5rem;
  right: 2.5rem;
  z-index: 20;
  cursor: pointer;
}

.nav__background{
  background-image: linear-gradient(#000, #000);
  height: 3.75rem;
  width: 3.75rem;
  border-radius: 50%;
  position: fixed;
  top: 2.8125rem;
  right: 2.8125rem;
  z-index: 10;
  transition: transform .6s ease;
}

.nav__menu{
  height: 100vh;
  position: fixed;
  color:#00f;
  top: 0;
  left: 0;
  z-index: 15;
  opacity: 0;
  visibility: hidden;
  width: 0;
  transition: all .6s ease;
}

.nav__checkbox:checked ~ .nav__menu{
  opacity: 1;
  visibility: visible;
  width: 100%;
}

.nav__checkbox:checked ~ .nav__background{
  transform: scale(20);
}

body{
  background-color: #eee;
}

Here is the link

https://jsfiddle.net/1wcpz3ua/8/

  • Thank you! Do you think this is usable in a production site or could there be "issues"? (dumb question) Also, the only thing left now, with that solution, the background should be "fullscreen", currently the circle just shows half. Looks cool too, but it would have to fill the whole screen... – sigug Jul 28 '20 at 09:03
  • 1
    I have been using that kind of navigation menus and never had a problem. To change how much the circle covers, just modify the transform: scale() property. I used 20, but you can use 100 if that is what you need. you can configure it on the media queries if you are going to use any gradient. – Hector Martinez Jul 28 '20 at 09:10
  • Thanks again! So, this time really the last thing: I want to have the opened menu in center always, doesn't seem to work with adding ``` top: 50%; left: 50%; transform:translate(-50%,-50%); ``` though, there is some strange behaviour? – sigug Jul 28 '20 at 11:53
  • 1
    Make sure that you are adding it to .nav__list. Also, don't forget the " position: absolute; ". It should work. https://jsfiddle.net/uLfbn2th/ Here is the version where it doesn't slide in from the left. I just changed what the transition takes to opacity and transform. https://jsfiddle.net/uLfbn2th/1/ – Hector Martinez Jul 28 '20 at 12:09
  • Thanks so much for being so patient and helpful! – sigug Jul 28 '20 at 12:22
  • Damn, I just realized somethinge else, heh.. So with this solution it's not possible to remove the background circle around the hamburger, right (because that background is the one getting fullscreen)? – sigug Jul 28 '20 at 12:31
  • 1
    You mean the white circle? If so, you could change its color to transparent when the checkbox is checked. There are two circles in that solution, the white one (the label) and the black one (empty div). The black one is the one that expands. – Hector Martinez Jul 28 '20 at 12:40