はじめてのCSS3アニメーション

こんにちは。impressiveでwebデザイナーしている新田です。

最近のサイトを見ているとスクロールした時のエフェクトなどアニメーションを使うことが当たり前になってきました。
今回はアニメーション入門としてCSS3アニメーションの概要と実装を復習も兼ねて紹介します!

目次
━━

・css3アニメーションのメリット
・css3アニメーションのデメリット
・css3アニメーションを使うには?
・ハンバーガーメニューを動かそう
・まとめ


css3アニメーションのメリット
━━

・IE9以下でなければ全ブラウザで使用可能!
・スマホも問題なく動く!
・現在ベンダープレフィックスも不要!(-webkit-、-moz-などのことです)
・javascriptで記述するよりも処理が早い!
・cssの知識があれば感覚的に実装できる!


css3アニメーションのデメリット
━━

・コードの量が多くなる。
・一つ一つは軽いのですが、設置数が多くなると重くなる。そのためブラウザでテストしながら確認する必要があります。


css3アニメーションを使うには?
━━

cssでアニメーションさせるにはtransitionanimationの2種類の方法あります。

CSS transition
プロパティ値(transformやwidthなど)を指定してアニメーションを適用できる機能。
単純な動きをつけたい時に利用できます。
アニメーションのループができません。
hoverなどイベントを発生させないと実行できません。

▼ 書き方例 

div {
 transition: transform .3s;
 &:hover {
  transform: rotate(45deg);
 }
}


CSS animation

要素(divやbuttonなど)にキーフレームアニメーションを適用できる機能。
細かい動きをつけたい時に利用できます。
アニメーションのループが可能。
hoverはもちろん、サイトを読み込んだときもイベントを実行できます。

▼ 書き方例 

.animation {
  //アニメーションを適用する要素を指定する
 animation-name: rotation;
 //アニメーションが完了するまでの時間
 animation-duration: 2s;
 //アニメーションが変化する速度
 animation-timing-function: linear;
 //アニメーションをループさせる
 animation-iteration-count: infinite;

 //下記の記述で短縮も可能!
 animation: rotation 2s linear infinite;

 @keyframes rotation {
  from {
   transform: rotate(0deg);
  }
  to {
   transform: rotate(360deg);
  }
 }
}

keyframes内のfrom、toは0%、100%でも代替できます。
なので、25%や50%など間のパーセンテージを指定することも可能です!
animationプロパティの詳しい設定や記述はこちらのサイトで詳しく書かれてます。
https://dekiru.net/article/13266/


2つを比較してみました !
赤がtransition、青がanimationで動いてます。

▼ DEMO
https://codepen.io/nitta_shiori/full/bYrbEp


🍔🍔ハンバーガーメニューを動かそう🍔🍔
━━

CSS3アニメーションを使用してハンバーガーメニューを実装してみます!
hoverにもエフェクトをつけてみます。

▼ DEMO
https://codepen.io/nitta_shiori/full/vWjjoN
これから各メニューを解説していきますので、DEMOを開いたままご覧いただければと思います。m(_ _)m

共通HTML・SCSS

・HTML
 .textはクリックした際にMENU、CLOSEを表示させます。

<div class="hamburger">
    <div class="menu_icon">
        <span class="border border1"></span>
        <span class="border border2"></span>
        <span class="border border3"></span>
    </div>
    <span class="text"></span>
</div>

・SCSS
今回reset.cssを使用します。
また、幅や高さを指定している部分があるので使用する際はこれらを自身の環境に合わせて調整してください。

$gray: #333333;
$white: #ffffff;
$base-transition: all .3s;
$line-height: 4px;
$line-radius: 5px;

.container {
 width: 60%;
 margin: auto;
 padding: 50px 0;
 box-sizing: border-box;
 display: flex;
 justify-content: space-between;
 flex-wrap: wrap;
 font-family: "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", Meiryo, メイリオ, Osaka, "MS PGothic", arial, helvetica, sans-serif;
 section {
   padding: 0 30px;
   margin-bottom: 60px;
 }
}

h1 {
   text-align: center;
   color: $white;
   font-size: 20px;
   font-family: 'Roboto', sans-serif;
   &::after {
     display: block;
     content: "";
     width: 30px;
     margin: auto;
     margin-bottom: 30px;
     padding-bottom: 20px;
     border-bottom: 1px solid #666666;
   }
 }

/*-----  ベーススタイル -----*/

.hamburger {
 width: 50px;
 margin: auto;
 .menu_icon {
   position: relative;
   width: 50px;
   height: 35px;
   margin: 0 auto 10px;
 }
 .border {
   position: absolute;
   left: 0;
   display: inline-block;
   width: 100%;
   height: $line-height;
   border-radius: $line-radius;
   transition: $base-transition;
   background: $white;
 }
 .border1 {
   top: 0;
 }
 .border2 {
   top: 0;
   bottom: 0;
   margin: auto;
 }
 .border3 {
   bottom: 0px;
 }
 
 //MENUのテキストが入る場合のスタイル
 .text {
   display: inline-block;
   width: 100%;
   text-align: center;
   font-size: 14px;
   color: $white;
   transition: $base-transition;
   &::after {
     display: block;
     content: "MENU";
   }
 }
 .active {
   & + .text {
     &::after {
       content: "CLOSE";
     }
   }
 }
}

メニューをクリックした場合は.activeを付与するよう、jqueryで切り替えを制御します。

$(function(){
  $('.menu_icon').click(function(){
    $(this).toggleClass('active');
  })
});

1.type1

ホバー時:上下のラインが少し右にずれる
クリック時:上下のラインでクローズボタン

ホバー時はtransform: translateXの数値をずらしてます。
クリックすると中央のラインはopacityでフェードアウトし、上下のラインはそれぞれtransform: rotateで傾きとtranslateで位置を調整しています。
どちらもtransitionで制御してます。

.type1 {
 .menu_icon {
   &:hover {
     .border1 {
       transform: translateX(5px);
     }
     .border3 {
       transform: translateX(5px);
     }
   }
 }
 .active {
   .border1 {
     transform: translateX(0) translateY(16px) rotate(45deg)!important;
   }
   .border2 {
     opacity: 0;
   }
   .border3 {
     transform: translateX(0px)translateY(-16px) rotate(-45deg)!important;
   }
 }
}

2.type2

ホバー時:上下のラインが中央に寄る
クリック時:中央のラインが横に飛んでいく

ホバー時はtransform: translateYで内側に寄るよう数値をずらしてます。
クリック時は「1. 上下のラインでクローズボタン」の内容に、中央のラインをtransform: translateXで横に移動しながらフェードアウトさせてます。
どちらもtransitionで制御してます。

.type2 {
 .menu_icon {
   &:hover {
     .border1 {
       transform: translateY(3px);
     }
     .border3 {
       transform: translateY(-3px);
     }
   }
 }
 .active {
   .border1 {
     transform: translateY(16px) rotate(45deg)!important;
   }
   .border2 {
     left: 80%;
     opacity: 0;
   }
   .border3 {
     transform: translateX(0px)translateY(-16px) rotate(-45deg)!important;
   }
 }
}

3.type3

ホバー時:不揃いのラインの長さを揃える
クリック時:回転しながらクローズボタン

ホバー前のスタイルで三本線の長さをwidthでそれぞれ調整して、ホバー時にwidthが100%になるようにしてます。
クリックすると「1. 上下のラインでクローズボタン」のコードに親要素の.menu_iconにtransform:rotate(360deg)を付与させ一周回転させます。
どちらもtransitionで制御してます。

.type3 {
 .menu_icon {
   transform: rotate(0);
   transition: $base-transition;
   .border1 {
     width: 100%;
   }
   .border2 {
     width: 50%;
   }
   .border3 {
     width: 80%;
   }
   &:hover {
     .border2 {
       width: 100%;
     }
     .border3 {
       width: 100%;
     }
   }
 }
 .active {
   transform: rotate(360deg);
   .border1 {
     transform: translateY(16px) rotate(-45deg);
     width: 100%;
   }
   .border2 {
     opacity: 0;
   }
   .border3 {
     transform: translateY(-16px) rotate(45deg);
     width: 100%;
   }
 }
}


4.type4

ホバー時:ラインが右に横切る
クリック時:上下のラインが中央まで移動してクローズボタン

コードが長いので分けて説明します。

・メニューホバー時
元となるborderはbackground: transparent;で透明化させて、擬似要素の::afterは正規位置から左にずらし、overflowで見えないようにしてます。
ホバーしたときにはそれぞれのラインをずらして動くようtransitionで設定してます。

.type4 {
 overflow: hidden;
 .border {
   background: transparent;
   &::before {
     position: absolute;
     left: 0;
     display: block;
     content: "";
     width: 100%;
     height: $line-height;
     border-radius: $line-radius;
     background: $white;
     transition: $base-transition;
   }
   &::after {
     position: absolute;
     left: -100px;
     display: block;
     content: "";
     width: 100%;
     height: $line-height;
     border-radius: $line-radius;
     background: $white;
     transition: $base-transition;
   }
 }
 
 .border1,.border2,.border3 {
   &::before {
     transition: all 0s linear;
   }
 }

 &:hover {
   .border {
     &::before {
       left: 100px;
     }
     &::after {
       left: 0;
     }
   }
   .border1 {
     &::before {
       transition: all .2s linear;
     }
     &::after {
       transition: all .2s linear;
     }
   }
   .border2 {
     &::before {
       transition: all .25s linear;
     }
     &::after {
       transition: all .25s linear;
     }
   }
   .border3 {
     &::before {
       transition: all .3s linear;
     }
     &::after {
       transition: all .3s linear;
     }
   }
 }
 
 .border1 {
   animation: type4_menu_bar01 0.5s;
   //アニメーション終了時点のスタイルを適用
   animation-fill-mode: forwards;
 }
 .border3 {
   animation: type4_menu_bar03 0.5s;
   //アニメーション終了時点のスタイルを適用
   animation-fill-mode: forwards;
 }
}

・メニューホバー時メニュークリック時
上下のラインを中央に寄せてからバツ印に変形させるので2段階アニメーションする必要があります。
この場合、transitionでは補完できないのでanimationを使います。
また先ほどのホバーがここでも動作するのでtransitionを無効化させ、borderに色を指定します。

.active {
   .border {
     background: $white;
     transition: none;
     &::before {
       transition: none;
     }
     &::after {
       transition: none;
     }
   }
   .border1 {
     animation: type4_active_menu_bar01 0.5s forwards;
   }
   .border2 {
     opacity: 0;
   }
   .border3 {
     animation: type4_active_menu_bar03 0.5s forwards;
   }
   
   //メニュー閉じる際のアニメーション
   @keyframes type4_menu_bar01 {
     0% {
       transform: translateY(16px) rotate(45deg);
     }
     50% {
       transform: translateY(16px) rotate(0);
     }
     100% {
       transform: translateY(0) rotate(0);
     }
   }
   
   @keyframes type4_menu_bar03 {
     0% {
       transform: translateY(-16px) rotate(-45deg);
     }
     50% {
       transform: translateY(-16px) rotate(0);
     }
     100% {
       transform: translateY(0) rotate(0);
     }
   }
   
   //メニュー開く際のアニメーション
   @keyframes type4_active_menu_bar01 {
     0% {
       transform: translateY(0) rotate(0);
     }
     50% {
       transform: translateY(16px) rotate(0);
     }
     100% {
       transform: translateY(16px) rotate(45deg);
     }
   }
   
   @keyframes type4_active_menu_bar03 {
     0% {
       transform: translateY(0) rotate(0);
     }
     50% {
       transform: translateY(-15px) rotate(0);
     }
     100% {
       transform: translateY(-15px) rotate(-45deg);
     }
   }
 }

5.type5

.menu_iconの擬似要素にサークルのスタイルをつけ、borderにtransparentを付け透明化させます。
クリックさせたときに中央のラインは横に移動しながら高さをなくし、そのタイミングでサークルを回転させ徐々にラインが現れるようにしてます。
段階的にアニメーションさせてるのでanimationで制御してます。

.type5 {
 width: 80px;
 height: 80px;
 .menu_icon {
   margin-top: 44px;
   &::before {
     position: absolute;
     top: 50%;
     left: 50%;
     margin: -44px 0 0 -44px;
     display: block;
     content: "";
     width: 80px;
     height: 80px;
     border-radius: 50%;
     border: 4px solid transparent;
   }
 }
 
 .active {
   .border1 {
     transform: translateY(16px)rotate(45deg);
   }
   .border2 {
     left: 50%;
     opacity: 0;
     animation: type5_active_menu_bar02 .8s forwards;
   }
   .border3 {
     transform: translateY(-16px)rotate(-45deg);
   }
   &::before {
     animation: circle .3s .25s forwards;
   }
   
   @keyframes type5_active_menu_bar02 {
     100% {
       height: 0;
     }
   }
   
   @keyframes circle {
     0% {
       border-color: transparent;
       transform: rotate(0);
     }
     25% {
       border-color: transparent $white transparent transparent;
     }
     50% {
       border-color: transparent $white $white transparent;
     }
     75% {
       border-color: transparent $white $white $white;
     }
     100% {
       border-color: $white;
       transform: rotate(360deg);
     }
   }
 }
}


まとめ
━━

コピペやなんとなく使っていたcss3アニメーションですが、transitionanimationの2種類の使い方の理解が深めることができました✌︎
さらに手軽に実装したいとなるとライブラリがありますので時間がない時に活用できそうです。
https://www.nxworld.net/services-resource/css-animation-libraries.html

アニメーションがあるのとないとではユーザーからの印象や体験がだいぶ変わりますし、どんどん利用していきたいです!




この記事が気に入ったら、サポートをしてみませんか?気軽にクリエイターを支援できます。

7

s_nitta

はて報

情報発信初心者の株式会社インプレッシブのメンバーが、情報発信ができるようになるべく、社内の取り組みを発信するマガジン
コメントを投稿するには、 ログイン または 会員登録 をする必要があります。