tru_shar
tru_shar

Reputation: 147

Animated Hamburger toggle button not not working properly

I have created a menu with bootstrap but removed the default collapse class and added a custom class that uses absolute position to show the menu when the toggle button is clicked.

But whenever I click the button the top and bottom bar of the toggle button bounce and make the cross icon. It works perfectly while using the collapse class. CSS seems right. there are no position changes after the button is clicked.

const button = document.querySelector('button');

button.addEventListener('click', () => {
    button.ariaExpanded = !JSON.parse(button.ariaExpanded);
});
.custom {
  color: #fff;
  background-color: transparent;
  background-image: -webkit-gradient(linear, left top, left bottom, from(#0000004f), to(#00000000));
  background-image: linear-gradient(180deg, #0000004f 0%, #00000000 100%);
  padding-top: 1.5rem;
  z-index: 99;
}

.custom .title {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
}

.custom .title a {
  font-family: "Tinos", serif;
  color: #fff;
  text-decoration: none;
  line-height: 1.3;
}

.custom .title .main-title {
  font-size: 30px;
}

@media only screen and (max-width: 576px) {
  .custom .title .main-title {
    font-size: 20px;
  }
}

.custom .title .sub-title {
  font-size: 20px;
}

@media only screen and (max-width: 576px) {
  .custom .title .sub-title {
    font-size: 20px;
  }
}

.custom .menu {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
  text-transform: uppercase;
}

@media only screen and (max-width: 576px) {
  .custom .menu {
    background-color: #e2e2e2;
    color: black;
    text-transform: capitalize;
    -webkit-box-orient: vertical;
    -webkit-box-direction: reverse;
        -ms-flex-direction: column-reverse;
            flex-direction: column-reverse;
  }
}

.custom .menu a {
  color: #fff;
}

@media only screen and (max-width: 576px) {
  .custom .menu a {
    color: black;
    margin-left: 1.5rem;
    text-transform: capitalize;
  }
}

.custom .menu .secondary {
  font-size: 13px;
}

@media only screen and (max-width: 576px) {
  .custom .menu .secondary {
    color: black;
    font-family: "Cormorant Garamond", serif;
    font-size: 1rem;
  }
}

.custom .menu .secondary ul {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
      -ms-flex-direction: row;
          flex-direction: row;
  -webkit-box-pack: end;
      -ms-flex-pack: end;
          justify-content: flex-end;
  margin-bottom: 0;
}

@media only screen and (max-width: 576px) {
  .custom .menu .secondary ul {
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
        -ms-flex-direction: column;
            flex-direction: column;
    padding-left: 0;
  }
}

.custom .menu .secondary ul li {
  margin-left: 1.5rem;
  list-style: none;
  letter-spacing: 1.55px;
}

@media only screen and (max-width: 576px) {
  .custom .menu .secondary ul li {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    margin-left: 0;
    border-bottom: 1px solid #80808070;
  }
  .custom .menu .secondary ul li:last-child {
    border-bottom: none;
  }
}

.custom .menu .primary {
  font-size: 19px;
  margin-top: 0.313rem;
}

@media only screen and (max-width: 576px) {
  .custom .menu .primary {
    color: black;
    font-family: "Cormorant Garamond", serif;
    font-size: 1rem;
  }
}

.custom .menu .primary ul {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
      -ms-flex-direction: row;
          flex-direction: row;
  -webkit-box-pack: end;
      -ms-flex-pack: end;
          justify-content: flex-end;
  margin-bottom: 0;
}

@media only screen and (max-width: 576px) {
  .custom .menu .primary ul {
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
        -ms-flex-direction: column;
            flex-direction: column;
    padding-left: 0;
  }
}

.custom .menu .primary ul li {
  margin-left: 1.5rem;
  list-style: none;
  letter-spacing: 2px;
}

@media only screen and (max-width: 576px) {
  .custom .menu .primary ul li {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    margin-left: 0;
    border-bottom: 1px solid #80808070;
  }
  .custom .menu .primary ul li:last-child {
    padding: 0;
  }
  .custom .menu .primary ul li:nth-last-child(2) {
    border-bottom: none;
  }
}

.custom .menu .primary ul li i {
  font-size: 15px;
}

@media only screen and (max-width: 576px) {
  .custom .menu .primary ul li i {
    display: none;
  }
}

@media only screen and (max-width: 576px) {
  .custom .mobile-menu {
    display: none;
    position: fixed;
    top: 6.25rem;
    left: 0;
    width: 100%;
    -webkit-transition: all 0.2s;
    transition: all 0.2s;
  }
}

.custom .show-mobile-menu {
  display: block;
  -webkit-transition: all 0.2s;
  transition: all 0.2s;
}

.navbar-toggler.x:focus {
    outline: none;
    box-shadow: none;
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(1) {
    transform: rotate(45deg);
    transform-origin: 10% 10%;
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(2) {
    opacity: 0;
    filter: alpha(opacity=0);
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(3) {
    transform: rotate(-45deg);
    transform-origin: 10% 90%;
}
.navbar-toggler.x .icon-bar {
    width: 22px;
    display: block;
    height: 2px;
    background-color: #fff;
    transition: all 0.2s;
}

.navbar-toggler.x .icon-bar + .icon-bar {
    margin-top: 4px;
}
.navbar-toggler.x .icon-bar:nth-of-type(1) {
    transform: rotate(0);
}
.navbar-toggler.x .icon-bar:nth-of-type(2) {
    opacity: 1;
    filter: alpha(opacity=100);
}
.navbar-toggler.x .icon-bar:nth-of-type(3) {
    transform: rotate(0);
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<nav class="navbar navbar-expand-lg custom">
            <div class="container">
                <div class="title">
                    <a class="main-title" href="index"
                        >title</a
                    >
                    
                </div>
                <button
                    class="navbar-toggler x"
                    type="button"
                    data-bs-toggle="mobile-menu"
                    data-bs-target="#navbarTogglerDemo01"
                    aria-controls="navbarTogglerDemo01"
                    aria-expanded="false"
                    aria-label="Toggle navigation"
                >
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <div class="mobile-menu" id="navbarTogglerDemo01">
                    <div class="menu ms-auto">
                        <div class="secondary">
                            <ul>
                                <li>
                                    <a aria-current="page" href="architecture"
                                        >Architecture</a
                                    >
                                </li>                               
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </nav>

Upvotes: 0

Views: 409

Answers (2)

A Haworth
A Haworth

Reputation: 36512

If we transform only the rotations and not the positioning there will be times when the elements are in slightly the wrong place.

This snippet aims to end up with the center of each bar at the center of the hamburger and to translate and rotate smoothly from its initial position without having a slight 'jump'. The rotation is about the center of each bar.

const button = document.querySelector('button');

button.addEventListener('click', () => {
    button.ariaExpanded = !JSON.parse(button.ariaExpanded);
});
.custom {
  color: #fff;
  background-color: transparent;
  background-image: -webkit-gradient(linear, left top, left bottom, from(#0000004f), to(#00000000));
  background-image: linear-gradient(180deg, #0000004f 0%, #00000000 100%);
  padding-top: 1.5rem;
  z-index: 99;
}

.custom .title {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
}

.custom .title a {
  font-family: "Tinos", serif;
  color: #fff;
  text-decoration: none;
  line-height: 1.3;
}

.custom .title .main-title {
  font-size: 30px;
}

@media only screen and (max-width: 576px) {
  .custom .title .main-title {
    font-size: 20px;
  }
}

.custom .title .sub-title {
  font-size: 20px;
}

@media only screen and (max-width: 576px) {
  .custom .title .sub-title {
    font-size: 20px;
  }
}

.custom .menu {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
  text-transform: uppercase;
}

@media only screen and (max-width: 576px) {
  .custom .menu {
    background-color: #e2e2e2;
    color: black;
    text-transform: capitalize;
    -webkit-box-orient: vertical;
    -webkit-box-direction: reverse;
        -ms-flex-direction: column-reverse;
            flex-direction: column-reverse;
  }
}

.custom .menu a {
  color: #fff;
}

@media only screen and (max-width: 576px) {
  .custom .menu a {
    color: black;
    margin-left: 1.5rem;
    text-transform: capitalize;
  }
}

.custom .menu .secondary {
  font-size: 13px;
}

@media only screen and (max-width: 576px) {
  .custom .menu .secondary {
    color: black;
    font-family: "Cormorant Garamond", serif;
    font-size: 1rem;
  }
}

.custom .menu .secondary ul {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
      -ms-flex-direction: row;
          flex-direction: row;
  -webkit-box-pack: end;
      -ms-flex-pack: end;
          justify-content: flex-end;
  margin-bottom: 0;
}

@media only screen and (max-width: 576px) {
  .custom .menu .secondary ul {
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
        -ms-flex-direction: column;
            flex-direction: column;
    padding-left: 0;
  }
}

.custom .menu .secondary ul li {
  margin-left: 1.5rem;
  list-style: none;
  letter-spacing: 1.55px;
}

@media only screen and (max-width: 576px) {
  .custom .menu .secondary ul li {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    margin-left: 0;
    border-bottom: 1px solid #80808070;
  }
  .custom .menu .secondary ul li:last-child {
    border-bottom: none;
  }
}

.custom .menu .primary {
  font-size: 19px;
  margin-top: 0.313rem;
}

@media only screen and (max-width: 576px) {
  .custom .menu .primary {
    color: black;
    font-family: "Cormorant Garamond", serif;
    font-size: 1rem;
  }
}

.custom .menu .primary ul {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
      -ms-flex-direction: row;
          flex-direction: row;
  -webkit-box-pack: end;
      -ms-flex-pack: end;
          justify-content: flex-end;
  margin-bottom: 0;
}

@media only screen and (max-width: 576px) {
  .custom .menu .primary ul {
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
        -ms-flex-direction: column;
            flex-direction: column;
    padding-left: 0;
  }
}

.custom .menu .primary ul li {
  margin-left: 1.5rem;
  list-style: none;
  letter-spacing: 2px;
}

@media only screen and (max-width: 576px) {
  .custom .menu .primary ul li {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    margin-left: 0;
    border-bottom: 1px solid #80808070;
  }
  .custom .menu .primary ul li:last-child {
    padding: 0;
  }
  .custom .menu .primary ul li:nth-last-child(2) {
    border-bottom: none;
  }
}

.custom .menu .primary ul li i {
  font-size: 15px;
}

@media only screen and (max-width: 576px) {
  .custom .menu .primary ul li i {
    display: none;
  }
}

@media only screen and (max-width: 576px) {
  .custom .mobile-menu {
    display: none;
    position: fixed;
    top: 6.25rem;
    left: 0;
    width: 100%;
    -webkit-transition: all 0.2s;
    transition: all 0.2s;
  }
}

.custom .show-mobile-menu {
  display: block;
  -webkit-transition: all 0.2s;
  transition: all 0.2s;
}

.navbar-toggler.x:focus {
    outline: none;
    box-shadow: none;
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(1) {
    transform: rotate(45deg) translateX(4px) translateY(4px);
    transform-origin: 50% 50%;
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(2) {
    opacity: 0;
    filter: alpha(opacity=0);
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(3) {
    transform: rotate(-45deg) translateX(4px) translateY(-4px);
    transform-origin: 50% 50%;
}
.navbar-toggler.x .icon-bar {
    width: 22px;
    display: block;
    height: 2px;
    background-color: #fff;
    transition: all 0.2s;
}

.navbar-toggler.x .icon-bar + .icon-bar {
    margin-top: 4px;
}
.navbar-toggler.x .icon-bar:nth-of-type(1) {
    transform: rotate(0) translateX(0) translateY(0);
}
.navbar-toggler.x .icon-bar:nth-of-type(2) {
    opacity: 1;
    filter: alpha(opacity=100);
}
.navbar-toggler.x .icon-bar:nth-of-type(3) {
    transform: rotate(0) translateX(0) translateY(0);
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<nav class="navbar navbar-expand-lg custom">
            <div class="container">
                <div class="title">
                    <a class="main-title" href="index"
                        >title</a
                    >
                    
                </div>
                <button
                    class="navbar-toggler x"
                    type="button"
                    data-bs-toggle="mobile-menu"
                    data-bs-target="#navbarTogglerDemo01"
                    aria-controls="navbarTogglerDemo01"
                    aria-expanded="false"
                    aria-label="Toggle navigation"
                >
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <div class="mobile-menu" id="navbarTogglerDemo01">
                    <div class="menu ms-auto">
                        <div class="secondary">
                            <ul>
                                <li>
                                    <a aria-current="page" href="architecture"
                                        >Architecture</a
                                    >
                                </li>                               
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </nav>

Upvotes: 1

flyingturtles
flyingturtles

Reputation: 903

I moved the transform-origin property to the basic css. When it was being applied later, it was somehow animating differently from others. Now it is working fine.

const button = document.querySelector('button');

button.addEventListener('click', () => {
    button.ariaExpanded = !JSON.parse(button.ariaExpanded);
});
.navbar-toggler.x:focus {
    outline: none;
    box-shadow: none;
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(1) {
    transform: rotate(45deg);
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(2) {
    opacity: 0;
    filter: alpha(opacity=0);
}
.navbar-toggler.x[aria-expanded='true'] .icon-bar:nth-of-type(3) {
    transform: rotate(-45deg);
}
.navbar-toggler.x .icon-bar {
    width: 22px;
    display: block;
    height: 2px;
    background-color: #fff;
        transition:all 0.2s;
}

.navbar-toggler.x .icon-bar + .icon-bar {
    margin-top: 4px;
}
.navbar-toggler.x .icon-bar:nth-of-type(1) {
    transform: rotate(0);
            transform-origin: 10% 10%;
}
.navbar-toggler.x .icon-bar:nth-of-type(2) {
    opacity: 1;
    filter: alpha(opacity=100);
}
.navbar-toggler.x .icon-bar:nth-of-type(3) {
    transform: rotate(0);
            transform-origin: 10% 90%;
}
<button class="navbar-toggler x" type="button" data-bs-toggle="mobile-menu" data-bs-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
  <span class="icon-bar"></span>
  <span class="icon-bar"></span>
  <span class="icon-bar"></span>
</button>

Upvotes: 1

Related Questions