Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
39
Help us understand the problem. What is going on with this article?
@amamamaou

三本線のメニューアイコンから×マークに変化するアニメーションいろいろ

More than 3 years have passed since last update.

CSSでアニメーションができるわけですし、どうせならちょっとアクセントをつけたいって感じのやつです。

三本線から×に変化させる

いろいろアイデアありますね。

JavaScriptはクラス名を変更するためだけにちょろっと使ってるだけなのでシンプルです。
チェックボックスを活用したJavaScriptを完全に使わない方法もありますが割愛。

まず、以下のHTMLとCSSは共通で使用するものとします。

HTML
<div class="menuWrapper">
  <a href="#menu" id="menuButton"><span>MENU</span></a>
</div>
CSS
.menuWrapper {
  position: relative;
  z-index: 0;
  border: 1px solid #ccc;
  width: 50px;
  height: 50px;
}

#menuButton {
  overflow: hidden;
  display: block;
  position: relative;
  z-index: 0;
  width: 50px;
  height: 50px;
  cursor: pointer;
}

#menuButton span,
#menuButton::before,
#menuButton::after {
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  left:0;
  right: 0;
  width: 36px;
  height: 4px;
  margin: auto;
  background: #000;
}
#menuButton span {
  overflow: hidden;
  z-index: 1;
  color: #000;
}
#menuButton::before {
  z-index: 2;
  transform: translate(0, -12px);
  content: "";
}
#menuButton::after {
  z-index: 2;
  transform: translate(0, 12px);
  content: "";
}

こんな感じの表示になります。

sample.png

サンプル1

sample1.gif

実際の動作サンプル1

CSS
#menuButton span {
  opacity: 1;
  transition: opacity 150ms 50ms;
}
#menuButton::before,
#menuButton::after {
  transition: transform 200ms;
}

#menuButton.active span {
  opacity: 0;
  transition: opacity 150ms;
}
#menuButton.active::before {
  transform: rotate(45deg);
}
#menuButton.active::after {
  transform: rotate(-45deg);
}
JavaScript
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('menuButton').addEventListener('click', function (ev) {
    ev.preventDefault();
    this.classList.toggle('active');
  });
});

サンプル2

sample2.gif

実際の動作サンプル2

CSS
#menuButton span {
  transition: transform 150ms 50ms;
}
#menuButton::before,
#menuButton::after {
  transition: transform 200ms;
}

#menuButton.active span {
  transform: translate(-50px, 0);
  transition: transform 150ms;
}
#menuButton.active::before {
  transform: rotate(45deg);
}
#menuButton.active::after {
  transform: rotate(-45deg);
}
JavaScript
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('menuButton').addEventListener('click', function (ev) {
    ev.preventDefault();
    this.classList.toggle('active');
  });
});

サンプル3

sample3.gif

実際の動作サンプル3

CSS
#menuButton {
  transition: transform 300ms;
}
#menuButton span {
  opacity: 1;
  transition: opacity 200ms;
}
#menuButton::before,
#menuButton::after {
  transition: transform 200ms;
}

#menuButton.active {
  transform: rotate(180deg);
}
#menuButton.active span {
  opacity: 0;
}
#menuButton.active::before {
  transform: rotate(45deg);
}
#menuButton.active::after {
  transform: rotate(-45deg);
}
JavaScript
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('menuButton').addEventListener('click', function (ev) {
    ev.preventDefault();
    this.classList.toggle('active');
  });
});

サンプル4

sample4.gif

実際の動作サンプル4

CSS
@keyframes lineTop {
  50% {
    transform: translate(0, 0);
  }
  100% {
    transform: rotate(45deg);
  }
}
@keyframes lineMiddle {
  50%, 100% {
    opacity: 0;
  }
}
@keyframes lineBottom {
  50% {
    transform: translate(0, 0);
  }
  100% {
    transform: rotate(-45deg);
  }
}

#menuButton.active span {
  animation: lineMiddle 250ms step-end forwards;
}
#menuButton.active::before {
  animation: lineTop 250ms forwards;
}
#menuButton.active::after {
  animation: lineBottom 250ms forwards;
}

#menuButton.default span {
  animation: lineMiddle 250ms step-end reverse;
}
#menuButton.default::before {
  animation: lineTop 250ms reverse;
}
#menuButton.default::after {
  animation: lineBottom 250ms reverse;
}
JavaScript
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('menuButton').addEventListener('click', function (ev) {
    var classList = this.classList;
    ev.preventDefault();
    if (classList.contains('active')) {
      classList.remove('active');
      requestAnimationFrame(function () {
        classList.add('default');
      });
    } else {
      classList.remove('default');
      requestAnimationFrame(function () {
        classList.add('active');
      });
    }
  });
});

大きさやアニメーションの速度などいじって自分好みにカスタマイズしてみるといいかもしれません。

39
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
amamamaou
ドット絵を嗜む人です

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
39
Help us understand the problem. What is going on with this article?