CSSだけで作るアニメーション付きドロップダウンメニュー【スマホ対応】

CSSだけでシンプルなドロップダウンメニューを作る方法を紹介します。

アニメーションを付ける場合、以前はJavascriptを使って動的にプロパティを変えていく必要がありました。
しかし、最近ではCSS3で追加された “transition” プロパティで徐々に変化させることもできるようになりました。

CSSで中央揃えやアスペクト比を固定した要素の作り方を紹介したこちらの記事もどうぞ。

(追記)
完成したメニューのデザインが寂しかったので、ちゃんと使える程度のサンプルを作りました。


基本的な考え方

CSSでは、疑似クラスといってユーザの動作に応じてスタイルを適応させることができます。
今回使う疑似クラスは “:hover” で、マウスが要素の上に乗った時に適応されます。
(スマホなどの場合はタッチして、他の要素がタッチされるまで)

また、アニメーションは初めの状態 (スタイル) と最終的な状態 (スタイル) をしていして、その間を “transition” プロパティで指定した時間を掛けて徐々に変化させます。

これらを組み合わせてドロップダウンさせます。

“:hover疑似クラス” でのプロパティ変更方法

例えば、マウスオーバーで要素の背景色を変える場合は以下のようにします。

イベント時に背景色が変わります
<CSS>

<style>
.sample{
    border:1px solid black;
    background-color:#FFDDDD;
}
.sample:hover{
    background-color:#DDFFFF;
}
</style>
<HTML>

<div class="sample" ontouchstart="">
    イベント時に背景色が変わります
</div>

ここで、注意が必要なことがあります。

最近のスマホでは殆ど問題ないのですが、古いiPhoneやタブレット端末などでは疑似クラスの “:hover” が効かないことがあります。
そんな場合に備えて要素に “ontouchstart” という属性を追加して下さい。
値は空白のままで構いません。
この属性を追加することで “:hover” が有効になるようです。

“transition” プロパティでアニメーション

アニメーションを行うには要素に “transition” プロパティを追加します。
“:hover疑似クラス” 側に指定すると初期状態から変化後への遷移時はアニメーションが発生しますが、初期状態への復帰時はすぐに元の状態へ戻るようになります。

普通のセレクタにtransitionを指定
“:hover疑似クラス” にtransitionを指定
<CSS>

<style>
// 普通のセレクタにtransitionを指定する場合
.sample{
    border:1px solid black;
    background-color:#FFFF99;
    transition:2.5s;
}
.sample:hover{
    background-color:#BBBBFF;
}

// ":hover疑似クラス" にtransitionを指定する場合
.sample{
    border:1px solid black;
    background-color:#FFFF99;
}
.sample:hover{
    background-color:#BBBBFF;
    transition:2.5s;
}
</style>
<HTML>

<div class="sample" ontouchstart="">
    徐々に背景色が変わります
</div>

上から詳細が出てくるメニュー

ドロップダウンメニューと聞いたらまず思い浮かべるメニューです。
アニメーションは分かりやすいように遅くしてあります。

カテゴリ名などのドロップダウンしていない状態で表示されている要素の下にドロップダウンする要素を隠しておいて、マウスオーバーで位置を表示させたい位置に移動させます。

  • MENU 1
  • PAGE 1
  • PAGE 2
  • PAGE 3
  • PAGE 4
  • MENU 1
  • PAGE 1
  • PAGE 2
  • PAGE 3
  • PAGE 4
<CSS>

<style>
  ul.drop1{
      display           : inline-block;
      position          : relative;
      list-style-type   : none;
      width             : 100px;
      padding           : 0px;
      margin-left       : 10px;
  }
  ul.drop1 li{
      position          : absolute;
      cursor            : pointer;
      top               : 0px;
      left              : 0px;
      box-sizing        : content-box;
      width             : 100px;
      height            : 35px;
      line-height       : 35px;
      text-align        : center;
      border            : 1px solid #BBB;
      background-color  : #FDF;
      transition        : top 0.7s, background-color 0s;
  }
  ul.drop1 li:hover{
      background-color  : #FFD;
  }
  ul.drop1 li.category{
      position          : relative;
      z-index           : 10;
      background-color  : #DFF;
  }
  ul.drop1 li.category1{
      z-index           : 4;
  }
  ul.drop1 li.category2{
      z-index           : 3;
  }
  ul.drop1 li.category3{
      z-index           : 2;
  }
  ul.drop1 li.category4{
      z-index           : 1;
  }
  ul.drop1:hover li.category1{
      top               : 35px;
  }
  ul.drop1:hover li.category2{
      top               : 70px;
  }
  ul.drop1:hover li.category3{
      top               : 105px;
  }
  ul.drop1:hover li.category4{
      top               : 140px;
  }
</style>
<HTML>

<ul class="drop1" ontouchstart="">
  <li class="category" >MENU 1</li>
  <li class="category1">PAGE 1</li>
  <li class="category2">PAGE 2</li>
  <li class="category3">PAGE 3</li>
  <li class="category4">PAGE 4</li>
</ul>

<ul class="drop1" ontouchstart="">
  <li class="category" >MENU 1</li>
  <li class="category1">PAGE 1</li>
  <li class="category2">PAGE 2</li>
  <li class="category3">PAGE 3</li>
  <li class="category4">PAGE 4</li>
</ul>

詳細が何もないところから出てくるメニュー

次は “transform” プロパティを使って何もないところから徐々に出てくるメニューです。
“transform” では色々な変形ができるので、色々試してみて下さい。

“transform” プロパティで変形すると (scale(0)やrotateY(90deg)で) 見えなくしていたメニューをクリックやタップすると “:hover” が効いてしまうので、最初は見えない位置まで移動させて誤動作を防いでいます。
他に良い方法があるよ、という方は良ければ教えて下さい。

  • MENU 2
  • PAGE 1
  • PAGE 2
  • PAGE 3
  • PAGE 4
  • MENU 3
  • PAGE 1
  • PAGE 2
  • PAGE 3
  • PAGE 4
<CSS>

<style>
  ul.drop2{
      display           : inline-block;
      position          : relative;
      list-style-type   : none;
      width             : 100px;
      padding           : 0px;
      margin-left       : 10px;
  }
  ul.drop2 li{
      position          : relative;
      cursor            : pointer;
      top               : 0px;
      left              : 99999px;
      width             : 100px;
      height            : 35px;
      line-height       : 35px;
      margin-bottom     : -1px;
      text-align        : center;
      border            : 1px solid #BBB;
      background-color  : #FDF;
      transform         : rotateX(90deg);
      transition        : transform 1.2s, left 0s, background-color 0s;
  }
  ul.drop2 li:hover{
      background-color  : #FFD;
  }
  ul.drop2 li.category2{
      left              : 0px;
      transform         : rotateX(0deg);
      background-color  : #DFF;
  }
  ul.drop2:hover li{
      left              : 0px;
      transform         : rotateX(0deg);
  }
  ul.drop3{
      display           : inline-block;
      position          : relative;
      list-style-type   : none;
      width             : 100px;
      padding           : 0px;
      margin-left       : 10px;
  }
  ul.drop3 li{
      position          : relative;
      cursor            : pointer;
      top               : 0px;
      left              : 99999px;
      width             : 100px;
      height            : 35px;
      line-height       : 35px;
      margin-bottom     : -1px;
      text-align        : center;
      border            : 1px solid #BBB;
      background-color  : #FDF;
      transform         : scale(0);
      transition        : transform 1.2s linear, left 0s, background-color 0s;
  }
  ul.drop3 li:hover{
      background-color  : #FFD;
  }
  ul.drop3 li.category3{
      left              : 0px;
      transform         : scale(1);
      background-color  : #DFF;
  }
  ul.drop3:hover li{
      left              : 0px;
      transform         : scale(1);
  }
</style>
<HTML>

<ul class="drop2" ontouchstart="">
  <li class="category2">MENU 2</li>
  <li>PAGE 1</li>
  <li>PAGE 2</li>
  <li>PAGE 3</li>
  <li>PAGE 4</li>
</ul>
<ul class="drop3" ontouchstart="">
  <li class="category3">MENU 3</li>
  <li>PAGE 1</li>
  <li>PAGE 2</li>
  <li>PAGE 3</li>
  <li>PAGE 4</li>
</ul>

デザインしたサンプルメニュー

ちょっと上記のメニューでは味気ないのでちゃんとデザインしたメニューも作ってみました。

HTML や CSS で不明なところがありましたら、コメントやお問い合わせよりご連絡下さい。

<CSS>

ul#menubar_sample{
  display             : flex;
  width               : 80%;
  margin              : 10px auto;
  padding             : 0px;
  list-style-type     : none;
  color               : #E6E6E6;
}
ul#menubar_sample > li{
  flex-grow           : 1;
  width               : 33.3%;
  margin              : 0px;
  padding             : 0px;
  font-size           : 14px;
  line-height         : 30px;
  background          : linear-gradient(0deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.5));
  text-align          : center;
  position            : relative;
  transition          : 0.45s ease-in-out;
}
ul#menubar_sample > li > ul{
  position            : absolute;
  top                 : 30px;
  left                : 0px;
  margin              : 0px;
  padding             : 0px;
  width               : 100%;
  list-style-type     : none;
}
ul#menubar_sample > li > ul > li{
  position            : relative;
  left                : -100%;
  opacity             : 0;
  background          : linear-gradient(0deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.5));
  font-size           : 14px;
  line-height         : 30px;
  height              : 0px;
  overflow            : hidden;
  transition          : all 0.45s ease-in-out, opacity 0.45s cubic-bezier(0.88, 0, 0.88, 1);
}
ul#menubar_sample > li > ul > li:nth-child(1){
  transition-delay    : 0.00s;
}
ul#menubar_sample > li > ul > li:nth-child(2){
  transition-delay    : 0.05s;
}
ul#menubar_sample > li > ul > li:nth-child(3){
  transition-delay    : 0.10s;
}
ul#menubar_sample > li > ul > li:nth-child(4){
  transition-delay    : 0.15s;
}
ul#menubar_sample > li > ul > li:nth-child(5){
  transition-delay    : 0.20s;
}
ul#menubar_sample > li > ul > li::before{
  content             : '.';
  opacity             : 0;
}
ul#menubar_sample > li:hover{
  background          : linear-gradient(0deg, rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0.7));
}
ul#menubar_sample > li:hover > ul > li{
  left                : 0%;
  opacity             : 1;
  height              : auto;
  background          : linear-gradient(0deg, rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0.7));
}
ul#menubar_sample li > a{
  position            : absolute;
  top                 : 0px;
  bottom              : 0px;
  left                : 0px;
  right               : 0px;
  color               : inherit;
  transition          : 0.45s;
}
ul#menubar_sample li > a:hover{
  text-decoration     : none;
  color               : #D9D9FF
}

<HTML>

<ul id="menubar_sample">
  <li>
    <a href="#">写真</a>
    <ul>
      <li>
        <a href="#">カメラ本体</a></li>
      <li>
        <a href="#">レンズ</a></li>
      <li>
        <a href="#">撮影方法</a></li>
    </ul>
  </li>
  <li>
    <a href="#">パソコン</a>
    <ul>
      <li>
        <a href="#">自作PC</a></li>
      <li>
        <a href="#">オススメ</a></li>
      <li>
        <a href="#">小技集</a></li>
    </ul>
  </li>
  <li>
    <a href="#">電子回路</a>
    <ul>
      <li>
        <a href="#">アナログ回路</a></li>
      <li>
        <a href="#">シミュレータ</a></li>
    </ul>
  </li>
</ul>

まとめ

以上、CSSのみでアニメーション付きのドロップダウンメニューを作る方法でした。

今回は余計な装飾をせず味気ないメニューでしたがグラデーションにしたり半透明にするだけでもカッコいいメニューが作れるので色々試してみて下さい。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)