スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

jQueryとCSS3を使ったアコーディオンメニューを詳しく説明します

jQueryとCSS3を使ったアコーディオンメニューを作ってみましたので、作り方を紹介します。かなり長くなりますが、お役に立てばうれしいです。

jquery-css-accordion.png

まず、サンプルは別サーバーに置いていますのでご覧ください。アコーディオンはjQueryで作っていますのでIEでも機能的には大丈夫です。

色々事情があってIEでご覧になっている方のためにスクリーンショットも載せておきます。カテゴリー3にマウスを乗せているところです。

jquery-css-accordion2.png

それではコードを解説していきます。

HTML

まずはHTMLです。無駄に長いですが一応載せます。

<ul id="accordion">
  <li><a href="#">カテゴリー1<span class="arrow rotate"></span></a>
    <ul id="active">
      <li><a href="#">サブカテゴリー1</a></li>
      <li><a href="#">サブカテゴリー2</a></li>
      <li><a href="#">サブカテゴリー3</a></li>
    </ul>
  </li>
  <li><a href="#">カテゴリー2<span class="arrow"></span></a>
    <ul>
      <li><a href="#">サブカテゴリー1</a></li>
      <li><a href="#">サブカテゴリー2</a></li>
      <li><a href="#">サブカテゴリー3</a></li>
      <li><a href="#">サブカテゴリー4</a></li>
    </ul>
  </li>
  <li><a href="#">カテゴリー3<span class="arrow"></span></a>
    <ul>
      <li><a href="#">サブカテゴリー1</a></li>
      <li><a href="#">サブカテゴリー2</a></li>
      <li><a href="#">サブカテゴリー3</a></li>
    </ul>
  </li>
  <li><a href="#">カテゴリー4<span class="arrow"></span></a>
    <ul>
      <li><a href="#">サブカテゴリー1</a></li>
      <li><a href="#">サブカテゴリー2</a></li>
      <li><a href="#">サブカテゴリー3</a></li>
      <li><a href="#">サブカテゴリー4</a></li>
      <li><a href="#">サブカテゴリー5</a></li>
    </ul>
  </li>
  <li><a href="#">カテゴリー5<span class="arrow"></span></a>
    <ul>
      <li><a href="#">サブカテゴリー1</a></li>
      <li><a href="#">サブカテゴリー2</a></li>
      <li><a href="#">サブカテゴリー3</a></li>
    </ul>
  </li>
</ul>

最初から開けておくカテゴリー部分には、2行目の「<span class="arrow rotate"></span>」のようにクラス「rotate」を追加し、3行目の「<ul id="active">」のようにID「active」を追加しておきます。

jQuery

続いてjQueryです。あまり得意じゃないのでもっと美しくて効率的な書き方もあるかもしれません。

まず、jQueryを読み込みます。恐らく一番人気があるGoogleのCDNを使います。別に他のCDNでも自分のサーバーにアップしてもかまいません。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
で、jQueryでアコーディオンの内容を記述します。
<script type='text/javascript'>
$(function() {
   $("#accordion li ul").hide();
   $("#active").show();
   $("#accordion > li > a").click(function(){
       var click = $("+ul",this);
	   click.slideDown();
       $("#accordion ul").not(click).slideUp();
	   $(".arrow").removeClass("rotate");
	   $("> .arrow",this).addClass("rotate");
       return false;
   });
});
</script>

せっかくなので1行ずつ説明します。

3行目:$("#accordion li ul").hide();

まずアコーディオンの中身を隠します。

4行目:$("#active").show();

アコーディオンの中身のうちid「active」が付いているもの(サブカテゴリー)を開けておきます。

5行目:$("#accordion > li > a").click(function(){

カテゴリ1~5の部分をクリックときの動きを5行目以下に書くことになります。「#accordion > li > a」の「>」は子要素にのみに適用させるときに使います。「#accordion li a」だとサブカテゴリーの部分を示す「#accordion li ul li a」にも反応してしまいますので、それを防ぐためです。

6行目:var click = $("+ul",this);

「$("+ul",this)」を変数「click」とします。thisは5行目で出てきた「#accordion > li > a(カテゴリーの部分)」のことで、「$("+ul",this)」はカテゴリーの隣のulとなります。クリックしたカテゴリーの中にあるサブカテゴリーのことです。この辺の指定の仕方はなかなか慣れないですね。

7行目:click.slideDown();

クリックしたカテゴリの中にあるサブカテゴリを開きます。

8行目: $("#accordion ul").not(click).slideUp();

クリックしたカテゴリー以外のサブカテゴリーを閉じます。この辺は知らない人でも何となくイメージできるのではないでしょうか。

9行目:$(".arrow").removeClass("rotate");

クラス名「arrow」の付いた要素から「rotate」のCSSを外します。

10行目:$("> .arrow",this).addClass("rotate");

クリックしたカテゴリーにある矢印の部分にクラス名「rotate」のCSSを追加します。

簡単にjQueryの設定を解説しましたが、慣れない方には難しいかもしれません。他にも色々方法はありますので、また別の機会に紹介したいと思います。

CSS

最後はCSSです。たくさんありますのでひとつずつ説明していきます。「-moz-」や「-webkit-」などのベンダープレフィックスは省いていますのでお気をつけください。最後にベンダープレフィックスを付けた全体のCSSも載せています。

ここで使っている色は0to255を使って選んでいます。かなり便利なWebツールですので知っておいて損はないと思います。使い方等は「カラーツール「0to255」で色を決めてメニューを作ってみる|Webpark」をご参考に。

Webフォントの読込み
@font-face {
	font-family: 'Typicons';
	src: url('fonts/typicons-regular-webfont.eot');
	src: url('fonts/typicons-regular-webfont.eot?#iefix') format('embedded-opentype'),
		url('fonts/typicons-regular-webfont.woff') format('woff'),
		url('fonts/typicons-regular-webfont.ttf') format('truetype'),
		url('fonts/typicons-regular-webfont.svg#TypiconsRegular') format('svg');
	font-weight: normal;
	font-style: normal;
}

まずはWebフォントを読み込みます。今回は「Typicons」のものを使いました。Webフォントについては以下の記事をご参考に。

アコーディオン全体
#accordion{
  list-style: none;
  width: 500px;
  font-size: 16px;
  line-height: 1;
  background-color: #add8e6;
  background-image: linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%,transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%,transparent 75%, transparent);
  background-size: 4px 4px;
  margin: 0;
  padding: 0;
  border-top: 15px solid #1b4958;
  border-bottom: 15px solid #1b4958;
  border-radius: 3px;
  box-shadow: 2px 3px 2px rgba(0,0,0,.2);
}

アコーディオン全体の設定になります。ブラウザ間の差異をなくすためにも色々指定しています。

背景はCSS3で斜線にしています。背景色「#add8e6」を指定して、その上に透明と透明度20%の白の斜線を重ねているイメージです。liやaで背景を指定してもいいのですが、斜線が途切れる可能性もありますのでここで指定します。

jquery-css-accordion5.png

上下に太めのボーダーを付けて角は丸くしています。あと全体にボックスシャドウを使っています。

カテゴリー1~5の部分
#accordion > li{
  padding: 0;
  border-right: 1px solid #3a9fc0;
  border-left: 1px solid #3a9fc0;
}

#accordionの子要素にあたるliに適用します。カテゴリー1~5の部分です。「#accordion li」にすると、サブカテゴリー内のli要素(#accordion li ul li)にも適用されるので注意しましょう。

ここではアコーディオンの両端のボーダーを指定しています。

カテゴリー1~5のリンク部分
#accordion li a{
  display: block;
  position:relative;
  color: #333;
  text-decoration:none;
  text-shadow: 0 1px 1px rgba(255,255,255,.7);
  padding: 15px 45px;
  border-bottom: 1px solid #79bfd6;
  border-top: 1px solid #eef7fa;
  transition: .3s;
}

先ほどのliの中にあるリンク部分に適用します。

上下にボーダーを引いていて、カテゴリー1の下のボーダーとカテゴリー2の上のボーダーという具合に2本のボーダーが重なっています。2本のボーダーが重なることでシャープな印象になります。

先ほど指定した左右のボーダーをここで指定すると、下の画像のようにボーダーが途切れてしまうので注意しましょう。

jquery-css-accordion3.png

2本のボーダーの効果などは「リストに1pxのラインを追加するだけで、印象がぐっとよくなる」をご参考に。

後で説明する左側のアイコンの基準となるよう「position:relative;」を指定します。

transitionについては、「CSS3のtransition-timing-functionの動きをサンプルで理解しよう」をご参考に。ベンダープレフィックスが必要ですのでご注意ください。

カテゴリー1の部分
#accordion > li:first-child > a{
  border-top: 0px;
}

1番上にある「カテゴリー1」の上のボーダーは必要ないので消しておきます。

カテゴリー1〜5の前にあるアイコン
#accordion > li a:before {
  position: absolute;
  top: 50%;
  left: 15px;
  font: 24px/100% 'Typicons';
  content: "\0023";
  color: #2f7f99;
  margin-top: -10px;
  text-shadow: 1px 1px 0px rgba(255,255,255,.7);
}

before疑似要素を使ってカテゴリー1〜5の前にアイコンを表示します。「#accordion > li > a」を基準にして、「position: absolute」で絶対位置で配置します。

jquery-css-accordion6.png

また、テキストシャドウで立体感を出しています。この辺の使い勝手の良さは画像にはないアイコン形式のWebフォントのメリットですね。

カテゴリー1〜5にマウスを乗せたとき
#accordion li a:hover{
  color: #1b4958;
  background: rgba(0,0,0,.1);
  border-top-color: #c7e4ee;
}

カテゴリー1〜5にマウスを乗せたときの設定です。背景を透明度の高い黒(rgba(0,0,0,.1))にしています。ちょっと濃い目の斜線になります。

RGBaカラーについては「透明度を表す「opacity」 と 「RGBa」の違いと使い分け」をご参考に。

カテゴリー1〜5の右にある矢印型のアイコンの位置
.arrow{
  position:absolute;
  top:50%;
  right: 30px;
  width: 30px;
  height: 20px;
  line-height: 1;
  text-shadow: 0 -1px 0px rgba(0,0,0,.3);
  margin-top: -10px;
  color: #d4ebf2;
  transition: .3s;
}

カテゴリー1〜5の右にある矢印の位置に関する設定です。実際の矢印は次に紹介するbefore疑似要素を使って表示します。こちらも「#accordion > li > a」を基準にして、「position: absolute」で絶対位置で配置します。

transitionを使ってマウスを乗せたときにスムーズに色が変わるようにしています。ここで指定しておくと後で紹介するbefore疑似要素を使って表示する矢印のアイコンの色もスムーズに変わります。

右端の矢印型のアイコン
.arrow:before{
  font: 30px 'Typicons';
  content: "7";
}

before疑似要素を使ってカテゴリー1〜5の後ろに矢印型のアイコンを表示します。

カテゴリー1〜5にマウスを乗せたときの矢印型のアイコン
#accordion li > a:hover .arrow{
  color: #2f7f99;
}

ここではアイコンの色だけ変えています。

jquery-css-accordion7.png

上が通常時、下がマウスを乗せたときです。

サブカテゴリーを開いているときの矢印
.rotate {
  color:#2f7f99;
  transform: rotate(90deg);
}

サブカテゴリーを開いているときの矢印を下向きにします。「transform: rotate(90deg)」で時計回りに90度傾けています。ベンダープレフィックスが必要となります。

jquery-css-accordion8.png

jQueryを使ってサブカテゴリーを開いたときに、このクラスを追加します。

サブカテゴリー全体
#accordion li ul {
  list-style: none;
  background: #e1f1f6;
  margin: 0;
  padding: 0;
}

サブカテゴリー全体の設定です。全体部分と同じようにulで背景色を付けています。こちらは斜線ではないのでliでもaでも大丈夫です。

jquery-css-accordion9.png
サブカテゴリー内の個別リンク
#accordion li ul li a{
  position:relative;
  background: none;
  line-height: 1;
  padding: 15px 70px;
  border-top: 1px solid #fff;
  border-bottom: 1px solid #a0d2e2;
}

サブカテゴリー内の個別リンクの設定です。親のカテゴリー部分と同じようにボーダーを2つ重ねています。背景が薄いのでボーダーも薄めにしています。

サブカテゴリー1〜5の前にあるアイコン
#accordion li ul li a:before {
  position: absolute;
  top: 50%;
  left:45px;
  content: "x";
  font:16px/100% 'Typicons';
  color: #2f7f99;
  margin-top: -8px;
  text-shadow: 1px 1px 0 rgba(0,0,0,.5);
  transition: .3s;
}

「#accordion li ul li a」を基準にして、「position: absolute」で絶対位置で配置します。これもテキストシャドウで立体感を出しています。

1番上にあるサブカテゴリー
#accordion li ul li:first-child a{
  border-top: 0px;
  box-shadow: 0 7px 7px -7px rgba(0,0,0,.5) inset;
}

これも親のカテゴリー1と同じように1番上のボーダーを消します。また、上側に影を付けることで立体感を出しています。

1番下にあるサブカテゴリー
#accordion li ul li:last-child a{
  border-bottom: 1px solid #5fb3ce;
}

一見必要なさそうですが、開いたときは親カテゴリとの境界線になりますので必要です。最初の状態でいうとサブカテゴリー3とカテゴリー2の境界線の上側のボーダー(濃い方)になります。

jquery-css-accordion10.png
サブカテゴリーにマウスを乗せたとき
#accordion li ul li a:hover{
  background: #d4ebf2;
  border-top-color: #eef7fa;
}

サブカテゴリーにマウスを乗せたときの設定になります。背景色と上のボーダーの色を若干濃くしています。

ということで個別に説明していきました。

CSS全体

これらをベンダープレフィックス付きでつなげるとこんな感じになります。かなり長いです。

@font-face {
  font-family: 'Typicons';
  src: url('fonts/typicons-regular-webfont.eot');
  src: url('fonts/typicons-regular-webfont.eot?#iefix') format('embedded-opentype'),
    url('fonts/typicons-regular-webfont.woff') format('woff'),
    url('fonts/typicons-regular-webfont.ttf') format('truetype'),
    url('fonts/typicons-regular-webfont.svg#TypiconsRegular') format('svg');
  font-weight: normal;
  font-style: normal;
}
#accordion{
  list-style: none;
  width: 500px;
  font-size: 16px;
  line-height: 1;
  background-color: #add8e6;
  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%,transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%,transparent 75%, transparent);
  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%,transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%,transparent 75%, transparent);
  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%,transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%,transparent 75%, transparent);
  background-image: -ms-linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%,transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%,transparent 75%, transparent);
  background-image: linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%,transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%,transparent 75%, transparent);
  -moz-background-size: 4px 4px;
  -webkit-background-size: 4px 4px;
  -o-background-size: 4px 4px;
  -ms-background-size: 4px 4px;
  background-size: 4px 4px;
  margin: 0;
  padding: 0;
  border-top: 15px solid #1b4958;
  border-bottom: 15px solid #1b4958;
  border-radius: 3px;
  box-shadow: 2px 3px 2px rgba(0,0,0,.2);
}
#accordion > li{
  padding: 0;
  border-right: 1px solid #3a9fc0;
  border-left: 1px solid #3a9fc0;
}
#accordion li a{
  display: block;
  position:relative;
  color: #333;
  text-decoration:none;
  text-shadow: 0 1px 1px rgba(255,255,255,.7);
  padding: 15px 45px;
  border-bottom: 1px solid #79bfd6;
  border-top: 1px solid #eef7fa;
  -moz-transition: .3s;
  -webkit-transition: .3s;
  -o-transition: .3s;
  -ms-transition: .3s;
  transition: .3s;
}
#accordion > li:first-child > a{
  border-top: 0px;
}
#accordion > li a:before {
  position: absolute;
  top: 50%;
  left: 15px;
  font: 24px/100% 'Typicons';
  content: "\0023";
  color: #2f7f99;
  margin-top: -10px;
  text-shadow: 1px 1px 0px rgba(255,255,255,.7);
}
#accordion li a:hover{
  color: #1b4958;
  background: rgba(0,0,0,.1);
  border-top-color: #c7e4ee;
}
.arrow{
  position:absolute;
  top:50%;
  right: 30px;
  width: 30px;
  height: 20px;
  line-height: 1;
  text-shadow: 0 -1px 0px rgba(0,0,0,.3);
  margin-top: -10px;
  color: #d4ebf2;
  -moz-transition: .3s;
  -webkit-transition: .3s;
  -o-transition: .3s;
  -ms-transition: .3s;
  transition: .3s;
}
.arrow:before{
  font: 30px 'Typicons';
  content: "7";
}
#accordion li > a:hover .arrow{
  color: #2f7f99;
}
.rotate {
  color:#2f7f99;
  -moz-transform: rotate(90deg);
  -webkit-transform: rotate(90deg);
  -o-transform: rotate(90deg);
  -ms-transform: rotate(90deg);
  transform: rotate(90deg);
}
#accordion li ul {
  list-style: none;
  background: #e1f1f6;
  margin: 0;
  padding: 0;
}
#accordion li ul li a{
  position:relative;
  background: none;
  line-height: 1;
  padding: 15px 70px;
  border-top: 1px solid #fff;
  border-bottom: 1px solid #a0d2e2;
}
#accordion li ul li a:before {
  position: absolute;
  top: 50%;
  left:45px;
  content: "x";
  font:16px/100% 'Typicons';
  color: #2f7f99;
  margin-top: -8px;
  text-shadow: 1px 1px 0 rgba(0,0,0,.5);
  -moz-transition: .3s;
  -webkit-transition: .3s;
  -o-transition: .3s;
  -ms-transition: .3s;
  transition: .3s;
}
#accordion li ul li:first-child a{
  border-top: 0px;
  box-shadow: 0 7px 7px -7px rgba(0,0,0,.5) inset;
}
#accordion li ul li:last-child a{
  border-bottom: 1px solid #5fb3ce;
}
#accordion li ul li a:hover{
  background: #d4ebf2;
  border-top-color: #eef7fa;
}

ベンダープレフィックスが必要なくなればかなり省略できると思いますがまだまだ先の話ですね。

これだけ長くなると見るだけで拒否反応を示す方もいるかもしれませんが、1つずつ順番に考えていけば難しいことはないと思います。

フィードやTwitterで最新情報をチェック
follow us in feedly
この記事に付いているタグの最新記事一覧
loading...
コメント
よく見ました。勉強になりました。いつもいい情報有り難うございます。
失礼ですけど、質問があります。”pure CSS”だけでアコーディオンは
無理ですか。jqueryの”click”代わりに:hover使って作ってみました。
何か似っていますけど、jqueryを利用する例では最初にアコーディオン
の中身のうち id active が付いているもの(サブカテゴリー)が開けて
います。しかし、私が作ったものはそうではなかったんです。
この部分が何十分も、考えても全然分からないんです。何か方法ありそう
ですけど、私には無理ですよ。HELP ME!!!
【2013/04/13 04:17】 | JeeWon #ofxKis3k | [edit]
JeeWonさん

コメントありがとうございます!

hoverだとマウスを離したときに閉じてしまうと思います。
今回のアコーディオンに近づけるにはラジオボタンを使うと
いいと思います。
【2013/04/13 06:07】 | 管理人 #E2ywrYdA | [edit]
おはようございます。hoverを使ってもマウスを離したときに閉じてしまいますね。。
しかし、いろいろ問題ですね。初画面でまっ上のsub-categoryが開けっぱなしに
なっていればいいんですけど、思うようには行けないんです。日本語が下手です。
すみません。ㅜ_ㅜ。。。 では、次の御記事、楽しみにしています。あ!ラジオボタン
も利用してみるようにします。ありがとうございます。^^
【2013/04/13 15:27】 | JeeWon #ofxKis3k | [edit]
JeeWon さん

hoverを使うと最初から開けておくというのは難しいと思います。
ラジオボタンを使ったアコーディオンメニューを作って
次の記事にしようと思いますのでぜひご覧ください~
【2013/04/13 16:38】 | 管理人 #E2ywrYdA | [edit]
はい。わかりました。^^
【2013/04/13 19:57】 | JeeWon #ofxKis3k | [edit]
こちらのアコーディオンメニューを使わせていただいております。
あまり知識がないので色や数値を変える程度のことしかできないのですが…
一度開いたメニューを、もう一度クリックして閉じることってできないでしょうか?
そうなればさらに使い勝手が良いなと思いまして質問させていただきました。
大変恐縮ですが教えていただければ幸いです。
【2013/06/21 14:25】 | morinoOnik #xn2rtZ2Y | [edit]
morinoOnik さん

コメントありがとうございます。
ご質問の件ですが、jQueryの内容を変更と可能です。

jQueryの7行目のslideDownをslideToggleにすると
クリックで閉じることができます。

ただこれだけだと右のアイコンは閉じている状態でも
下を向いたままになってしまいます。

これについてもjQueryの変更で対応できますが
大幅に変える必要があるのでご容赦いただければと思います。
【2013/06/22 06:16】 | 管理人 #E2ywrYdA | [edit]
activeだとクリックが離されるまでの動作ですよね。もう一回クリックまでの動作ってできますか?(CSSのみで)
【2014/03/20 10:14】 | noname #IhXWtuA2 | [edit]
はじめまして。参考に勉強をさせてもらっているものです。

素直な記述で実践すると問題なく動くのですが、
変数化した場合に動かなくなるのは仕方ないのでしょうか?

$list変数にhtmlタグを記述しているのですが、
動かないのです・・・。
何か別の問題かもしれませんが、
何かヒントになればと思い質問させていただきました。

ご教授のほどよろしくお願いします。


a.js---大部分を抜粋)--------------------------------
var $list = '<ul id="accordion">';
for(i=1;i<contacts.length;i++){
$list += '<li><div class="main_menu">';
$list += contacts[i].displayName;
$list += '</div>\n';
$list += '</ul>\n</li>\n';
}
$list += '</ul>';
alert($list);
document.getElementById("list").innerHTML = $list;
-------------------------------
a.html---抜粋------------------------
<head>
<script>
//アコーディオンメニュー
$(function() {
$("#accordion li ul").hide();
$("#active").show();
$("#accordion > li > a").click(function(){
var click = $("+ul",this);
click.slideDown();
$("#accordion ul").not(click).slideUp();
$(".arrow").removeClass("rotate");
$("> .arrow",this).addClass("rotate");
return false;
});
});
</script>
</head>
<body onload=onload()>
  処理・・・・

<div id="list"></div>
</body>
-------------------------------------
【2014/09/25 16:01】 | 貴 #GCA3nAmE | [edit]
はじめまして、こちらのアコーディオンメニューを使わせていただきたいと思っています。なんせ初心者で・・・
いろいろ試してみたのですが、親要素?カテゴリー1~カテゴリー5にサブカテゴリーのようにリンクを貼りたいのですが、
全く無反応になってしまいます。
クリック時にサブが開くと同時にページが開かれるようにしたいのですが、どのようにすればよいか教えていただければありがたいです。
どうぞ、よろしくお願いします。
【2015/05/06 21:25】 | T--------z #BCk..gBM | [edit]









※コメントはご意見ご感想や間違いのご指摘等にしていただけますようお願いいたします。コメントを確認する時間がなく、技術的なご質問をいただいても答えできません。申し訳ございませんがご理解のほどお願いいたします。

Recent Entry
Popular Entry
  • このエントリーをはてなブックマークに追加
  • このエントリーをはてなブックマークに追加
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。