こんにちは!セミマサです。
クリックで開け閉めできるアコーディオンメニューは多くのウェブサイトで見かけますよね!今回はjQuery6パターン、HTML5のみ1パターン、CSSのみで2パターン、計9パターンのアコーディオンメニューを作ったので作成方法をまとめていきたいと思います。
※ソースに関して:複数回登場するクラス(accordion-inner等)は初出の部分にのみcssを記載しています。
jQuery/6パターン
複数開けるタイプ
よくあるタイプのアコーディオンメニューです。
HTML
<div class="accordion-inner">
<h3 class="heading">複数開けるタイプ</h3>
<div class="accordion-box column">
<p class="accordion">アコーディオンA</p>
<div class="accordion-content">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box column">
<p class="accordion">アコーディオンB</p>
<div class="accordion-content">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box column">
<p class="accordion">アコーディオンC</p>
<div class="accordion-content">
アコーディオンの中身です
</div>
</div>
</div>
CSS
.column {
display: flex;
flex-direction: column; }
.accordion-box {
justify-content: center;
align-items: center;
padding: 0 5%; }
.accordion-box + .accordion-box {
margin-top: 20px; }
.accordion{
border: 1px solid #ccc;
width: 100%;
text-align: left;
position: relative;
cursor: pointer;
background-color: white;
padding: 8px 0 8px 3%; }
.accordion::after{
content: '';
width: 8px;
height: 8px;
border: 0px;
border-top: solid 1px black;
border-right: solid 1px black;
-ms-transform: rotate(135deg);
-webkit-transform: rotate(135deg);
margin-left: -6px;
transform: rotate(135deg);
position: absolute;
top: 50%;
right: 4%;
margin-top: -5px; }
.accordion-inner {
padding: 30px 0 60px 0; }
.accordion-content {
display: none;
padding: 8px 0 8px 3%;
width: 100%;
text-align: left;
background-color: #e1a948; }
.heading{
padding: 0 5%;
margin-bottom: 10px;
}
CSSです。
・after疑似要素で下向きのマークを作っています。
・+セレクタを使って2番目以降のアコーディオンに上方向のマージンを当てています。
jQuery
$('.accordion').click(function () {
$(this).next().slideToggle(300);
});
・accordionクラスをクリックした際に、accordionクラスの次の要素をslideToggleメソッドを使って開け閉めしています。今回は300ミリ秒(0.3秒)を引数で与えています。
デモサイト
複数開けるタイプ(最初から開いているものアリ)
「複数開けるタイプ」とほぼ同じで、開けておきたいものにopenクラスを付与しています。 jQueryは同一なので掲載していません。
HTML
<div class="accordion-inner">
<h3 class="heading">複数開けるタイプ(最初から開いているものアリ)</h3>
<div class="accordion-box column">
<p class="accordion">アコーディオンA</p>
<div class="accordion-content open">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box column">
<p class="accordion">アコーディオンB</p>
<div class="accordion-content">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box column">
<p class="accordion">アコーディオンC</p>
<div class="accordion-content">
アコーディオンの中身です
</div>
</div>
</div>
CSS
.open{
display: block;
}
openクラスのcssです。
1つしか開けられないタイプ
HTMLとCSSは「複数開けられるタイプ」とほぼ同じです。
HTML
<div class="accordion-inner">
<h3 class="heading">1つしか開けられないタイプ</h3>
<div class="accordion-box column">
<p class="accordion-one">アコーディオンA</p>
<div class="accordion-content">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box column">
<p class="accordion-one">アコーディオンB</p>
<div class="accordion-content">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box column">
<p class="accordion-one">アコーディオンC</p>
<div class="accordion-content">
アコーディオンの中身です
</div>
</div>
</div>
CSS
.accordion-one{
border: 1px solid #ccc;
width: 100%;
text-align: left;
position: relative;
cursor: pointer;
background-color: white;
padding: 8px 0 8px 3%; }
.accordion-one::after{
content: '';
width: 8px;
height: 8px;
border: 0px;
border-top: solid 1px black;
border-right: solid 1px black;
-ms-transform: rotate(135deg);
-webkit-transform: rotate(135deg);
margin-left: -6px;
transform: rotate(135deg);
position: absolute;
top: 50%;
right: 4%;
margin-top: -5px; }
jQuery
$('.accordion-one').click(function () {
$(this).next().slideToggle(300);
$('.accordion-one').not($(this)).next().slideUp(300);
});
・1つしか開いていない状態にするため、notメソッドを使って「クリックしたaccordion-oneクラス」以外の「accordion-oneクラス」をslideUPメソッドで非表示にしています。
横に開くタイプ
HTML
<div class="accordion-inner">
<h3 class="heading">横に開くタイプ</h3>
<div class="accordion-box-side row">
<p class="accordion-side">アコーディオンA</p>
<div class="accordion-content-side">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box-side row">
<p class="accordion-side">アコーディオンB</p>
<div class="accordion-content-side">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box-side row">
<p class="accordion-side">アコーディオンC</p>
<div class="accordion-content-side">
アコーディオンの中身です
</div>
</div>
</div>
CSS
.row {
display: flex;
flex-direction: row; }
.accordion-side{
border: 1px solid #ccc;
width: 40%;
text-align: left;
position: relative;
cursor: pointer;
background-color: white;
padding: 8px 8px 8px 3%; }
.accordion-side::after{
content: '';
width: 8px;
height: 8px;
border: 0px;
border-top: solid 1px black;
border-right: solid 1px black;
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
margin-left: -6px;
transform: rotate(45deg);
position: absolute;
top: 50%;
right: 4%;
margin-top: -5px; }
.accordion-content-side {
display: none;
padding: 8px 8px;
width: 60%;
text-align: center;
white-space: nowrap;
background-color: #e1a948; }
.accordion-box-side {
justify-content: flex-start;
align-items: stretch;
padding: 0 5%; }
.accordion-box-side + .accordion-box-side {
margin-top: 20px; }
横向きということで多少CSSが変わっています。
・中身であるaccordion-content-sideクラスのwhite-spaceプロパティに改行をしなくなる「nowrap」を指定しています。こうしないと中身が縮んだ際にテキストが崩れて残念な表示になります。
・親要素の幅と子要素の幅を合わせて100%になるように指定。
・疑似要素のマークをrotateの数字を調整して右向きにしています。
jQuery
$('.accordion-side').click(function () {
$(this).next().animate({ width: 'toggle' }, 'normal');
});
横向きの場合はanimateメソッドを使います。
・クリックしたaccordion-sideクラスの「次の要素のwidthプロパティ」を、’toggle’指定を使って表示/非表示で切り替えています。速度には「normal」を指定しました。
横に開くタイプ(1つしか開けられない)
HTMLとCSSは「横に開くタイプ」とほぼ同じです。
HTML
<div class="accordion-inner">
<h3 class="heading">横に開くタイプ(1つしか開けられないタイプ)</h3>
<div class="accordion-box-side row">
<p class="accordion-side-one">アコーディオンA</p>
<div class="accordion-content-side">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box-side row">
<p class="accordion-side-one">アコーディオンB</p>
<div class="accordion-content-side">
アコーディオンの中身です
</div>
</div>
<div class="accordion-box-side row">
<p class="accordion-side-one">アコーディオンC</p>
<div class="accordion-content-side">
アコーディオンの中身です
</div>
</div>
</div>
CSS
.accordion-side-one{
border: 1px solid #ccc;
width: 40%;
text-align: left;
position: relative;
cursor: pointer;
background-color: white;
padding: 8px 8px 8px 3%; }
.accordion-side-one::after{
content: '';
width: 8px;
height: 8px;
border: 0px;
border-top: solid 1px black;
border-right: solid 1px black;
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
margin-left: -6px;
transform: rotate(45deg);
position: absolute;
top: 50%;
right: 4%;
margin-top: -5px; }
jQuery
$('.accordion-side-one').click(function () {
$(this).next().animate({
width: 'toggle'
}, 'normal');
$('.accordion-side-one').not($(this)).next().animate({
width: 'hide'
}, 'normal');
});
縦開きの1つしか開けられないタイプと同じく、notメソッドで「クリックしたaccordion-side-oneクラス」以外の「accordion-side-oneクラス」のwidthプロパティをanimateメソッドの’hide‘指定で非表示にしています。
カテゴリメニュー型
HTML
<div class="accordion-inner">
<h3 class="heading">カテゴリメニュー型</h3>
<div class="accordion-category-wrap row">
<div class="accordion-category-box">
<p class="accordion-category">大カテゴリA</p>
<ul class="category">
<li class="category-item"><a href="#">小カテゴリa</a></li>
<li class="category-item"><a href="#">小カテゴリb</a></li>
<li class="category-item"><a href="#">小カテゴリc</a></li>
<li class="category-item"><a href="#">小カテゴリd</a></li>
<li class="category-item"><a href="#">小カテゴリe</a></li>
<li class="category-item"><a href="#">小カテゴリf</a></li>
</ul>
</div>
<div class="accordion-category-box">
<p class="accordion-category">大カテゴリB</p>
<ul class="category">
<li class="category-item"><a href="#">小カテゴリa</a></li>
<li class="category-item"><a href="#">小カテゴリb</a></li>
<li class="category-item"><a href="#">小カテゴリc</a></li>
<li class="category-item"><a href="#">小カテゴリd</a></li>
<li class="category-item"><a href="#">小カテゴリe</a></li>
<li class="category-item"><a href="#">小カテゴリf</a></li>
</ul>
</div>
<div class="accordion-category-box">
<p class="accordion-category">大カテゴリC</p>
<ul class="category">
<li class="category-item"><a href="#">小カテゴリa</a></li>
<li class="category-item"><a href="#">小カテゴリb</a></li>
<li class="category-item"><a href="#">小カテゴリc</a></li>
<li class="category-item"><a href="#">小カテゴリd</a></li>
<li class="category-item"><a href="#">小カテゴリe</a></li>
<li class="category-item"><a href="#">小カテゴリf</a></li>
</ul>
</div>
<div class="accordion-category-box">
<p class="accordion-category">大カテゴリD</p>
<ul class="category">
<li class="category-item"><a href="#">小カテゴリa</a></li>
<li class="category-item"><a href="#">小カテゴリb</a></li>
<li class="category-item"><a href="#">小カテゴリc</a></li>
<li class="category-item"><a href="#">小カテゴリd</a></li>
<li class="category-item"><a href="#">小カテゴリe</a></li>
<li class="category-item"><a href="#">小カテゴリf</a></li>
</ul>
</div>
</div>
</div>
CSS
ul,li {
list-style: none;
}
.accordion-category-wrap {
justify-content: flex-start;
align-items: center;
flex-flow: wrap;
width: 100%;
padding: 0 5%;
}
.accordion-category-box{
width: 50%;
}
.accordion-category{
border: 1px solid #ccc;
padding: 8px;
position: relative;
}
.accordion-category::after{
content: '';
width: 8px;
height: 8px;
border: 0px;
border-top: solid 1px black;
border-right: solid 1px black;
-ms-transform: rotate(135deg);
-webkit-transform: rotate(135deg);
margin-left: -6px;
transform: rotate(135deg);
position: absolute;
top: 50%;
right: 4%;
margin-top: -5px;
}
.category{
width: 100%;
flex-flow: wrap;
justify-content: center;
align-items: center;
display: none;
}
.category-item{
background-color: azure;
padding: 8px;
border: 1px solid #ccc;
}
.category-item a{
width: 100%;
display: block;
}
jQuery
$('.accordion-category').click(function () {
$(this).next().slideToggle(300);
});
jQueryに関しては「複数開けるタイプ」と同様です。notメソッドを利用すれば1つしか開かなくすることもできます。
HTML5のみ/1パターン
detailsタグとsummaryタグを使います!
HTML
<div class="accordion-inner">
<h3 class="heading">縦開き</h3>
<details>
<summary>中身の要約</summary>
<p class="details-text">中身</p>
<p class="details-text">中身</p>
<p class="details-text">中身</p>
</details>
</div>
CSS
details{
padding: 10px 5%;
}
summary{
padding: 10px 0;
}
.details-text {
padding: 8px 8px 8px 16px;
background-color: #e1a948;
}
・detailsタグの子要素にsummaryタグを配置すればOKです。summaryタグと同階層にあるpタグは「detailsの内容」を示しており、メニューの中身になります。
※detailsタグとsummaryタグの本来の用途はdetailタグの内容をsummaryタグで要約することです。不適切なマークアップにならないよう内容に気を付けましょう!
CSS/2パターン
縦開き
HTML
<div class="accordion-inner">
<h3 class="heading">縦開き</h3>
<div class="accordion-box column">
<input type="checkbox" id="accordion-check">
<label class="accordion-label" for="accordion-check">アコーディオンA</label>
<div class="accordion-content-css">
アコーディオンの中身です
</div>
</div>
</div>
・labelタグのfor属性を使ってinputタグとlabelタグを紐づけます。こうすることでラベルがクリックされた際にチェックが入るようになります。
CSS
.accordion-label {
border: 1px solid #ccc;
width: 100%;
text-align: left;
position: relative;
cursor: pointer;
background-color: white;
padding: 8px 0 8px 3%; }
.accordion-label::after{
content: '';
width: 8px;
height: 8px;
border: 0px;
border-top: solid 1px black;
border-right: solid 1px black;
-ms-transform: rotate(135deg);
-webkit-transform: rotate(135deg);
margin-left: -6px;
transform: rotate(135deg);
position: absolute;
top: 50%;
right: 4%;
margin-top: -5px; }
#accordion-check{
display: none;
}
.accordion-content-css {
height:0;
padding: 0 0 0 3%;
width: 100%;
text-align: left;
background-color: #e1a948;
transition: all .3s;
opacity: 0;
}
#accordion-check:checked ~ .accordion-content-css{
padding: 8px 0 8px 3%;
height:32px;
opacity: 1;
}
・アコーディオンの中身である「accordion-content-css」の高さと不透明度を0にしておきます。
・「~」セレクタを使って条件分岐のようなことをしています。上のソースの場合、「#accordion-check」にチェックがついている場合、「accordion-content-css」クラスに括弧内の内容が適用されて表示されるようになります。
横開き
HTML
<div class="accordion-inner">
<h3 class="heading">横開き</h3>
<div class="accordion-box row">
<input type="checkbox" id="accordion-check2">
<label class="accordion-label-side" for="accordion-check2">アコーディオンA</label>
<div class="accordion-content-css-side">
アコーディオンの中身です
</div>
</div>
</div>
CSS
#accordion-check2{
display: none;
}
.accordion-label-side{
border: 1px solid #ccc;
width: 50%;
height:100%;
text-align: left;
position: relative;
cursor: pointer;
background-color: white;
padding: 8px 8px 8px 3%; }
.accordion-label-side::after{
content: '';
width: 8px;
height: 8px;
border: 0px;
border-top: solid 1px black;
border-right: solid 1px black;
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
margin-left: -6px;
transform: rotate(45deg);
position: absolute;
top: 50%;
right: 4%;
margin-top: -5px; }
.accordion-content-css-side {
opacity: 0;
padding: 8px 3% 8px 3%;
width: 50%;
text-align: center;
background-color: #e1a948;
transition: all .5s;
transform: translateX(-100%);
z-index: -2;
}
#accordion-check2:checked~.accordion-content-css-side {
padding: 8px 3% 8px 3%;
opacity: 1;
transform: translateX(0);
}
@media screen and (max-width: 480px) {
.accordion-content-css-side{
font-size: 0.8rem;
}
}
・仕組みは縦開きのものと同様で、最初はアコーディオンの中身である「accordion-content-css-side」の不透明度を0にしつつ「transform:tranlateX」で左にずらしておきます。チェックボックスにチェックが入ったら透明度を1にしつつ元の位置へ戻すようにしています。
おわりに
今回は9パターンのアコーディオンメニューを作成しました。アコーディオンメニューはjQueryで作ることが多かったのですがCSSのみでもなんとかなりそうですね!
CSSのセレクタはまだ使ったことがないものが多いのでうまく使えば複雑な動きもつけられるかもしれません。いろいろ試してみたいと思います。