cssとhtmlのcheckboxを使って、アコーディオンメニューを実装する
CSS

CSSとhtmlのcheckboxを使って高さ可変のアコーディオンメニューを実装するサンプル

アバター by pranktone
サンプルコード

CSSとcheckboxを使ってアコーディオンメニューを実装するサンプルです。

展開する要素の高さが変わっても(テキストの量が増えても)、大丈夫な作りにしました。

極力自然なアニメーションを心掛けたのですが、JavaScriptで実装した方が動きは滑らかな気がします。

別記事のjQueryのslideToggleを使ってアコーディオンを実装するサンプルと、ネイティブのJavaScript(脱jQuery)でアコーディオンメニューを実装するサンプルとの比較も兼ねて作ったので、htmlは似た構成にしています。

html

<input type="checkbox" name="accordion" class="accordion-checkbox" id="accordion-checkbox1" checked>
<label class="accordion-trigger" for="accordion-checkbox1">アコーディオン1</label>
<ul class="accordion-target list">
  <li class="list__item"><a href="#">メニュー1</a></li>
  <li class="list__item"><a href="#">メニュー2</a></li>
  <li class="list__item"><a href="#">メニュー3</a></li>
  <li class="list__item"><a href="#">メニュー4</a></li>
  <li class="list__item"><a href="#">メニュー5</a></li>
</ul><!-- .accordion-target -->

<input type="checkbox" name="accordion" class="accordion-checkbox" id="accordion-checkbox2">
<label class="accordion-trigger" for="accordion-checkbox2">アコーディオン2</label>
<ul class="accordion-target list">
  <li class="list__item"><a href="#">メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1メニュー1</a></li>
  <li class="list__item"><a href="#">長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気長いテキストも平気</a></li>
  <li class="list__item"><a href="#">メニュー3</a></li>
  <li class="list__item"><a href="#">メニュー4</a></li>
  <li class="list__item"><a href="#">メニュー5</a></li>
</ul><!-- .accordion-target -->

labelとinput type="checkbox"、アコーディオンの本体(ここでは'ul.accordion-target')の配置が肝です。

上記の要素が同列(兄弟関係)にないと動きません。

labelとそれぞれのinput type="checkbox"をforで紐づけるのも忘れないようにします。

最初から開いておきたい展開要素がある場合は、それに対応したトリガー要素のinput type="checkbox"に'checked'属性をつけます。

CSS

.accordion-checkbox { /* checbox */
  display: none;
}

.accordion-trigger { /* label */
  text-align: left;
  box-sizing: border-box;
  cursor: pointer;
  display: block;
  padding: 15px;
  padding-right: 42px; /* padding + icon width */
  border-bottom: 1px solid #ccc;
  background-color: lightblue;
  position: relative;
}

/* icon */
.accordion-trigger::before,
.accordion-trigger::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 15px;
  margin: auto;
  height: 2px;
  width: 12px;
  background-color: #000;
  transition: all .1s ease-out;
}

.accordion-trigger::after {
  transform: rotate(90deg);
}

/* /icon */

.accordion-target { /* target */
  box-sizing: border-box;
  visibility: hidden;
  opacity: 0;
  transition: all .4s ease-out;
  text-align: left;
}

.accordion-target.list > .list__item { /* target-child */
  box-sizing: border-box;
  height: 0;
  visibility: hidden;
  opacity: 0;
  padding-top: 0;
  padding-bottom: 0;
  transition:
    visibility .2s ease-out,
    opacity .2s ease-out,
    padding-top .4s ease-out,
    padding-bottom .4s ease-out;
}

.accordion-target.list > .list__item > a {
  display: block;
  padding: 0 15px;
  color: #000;
  text-decoration: none;
}

.accordion-checkbox:checked + .accordion-trigger::after {
  opacity: 0;
  transform: rotate(0);
}
.accordion-checkbox:checked + .accordion-trigger + .accordion-target {
  visibility: visible;
  opacity: 1;
}

.accordion-checkbox:checked + .accordion-trigger + .accordion-target > .list__item {
  visibility: visible;
  height: auto;
  border-bottom: 1px solid #ccc;
  opacity: 1;
  padding-top: 15px;
  padding-bottom: 15px;
  transition:
    visibility .2s ease-out .2s,
    opacity .2s ease-out .2s,
    padding-top ease-out .4s,
    padding-bottom ease-out .4s;
}

.accordion-checkbox:checked + .accordion-trigger + .accordion-target > .list__item > a{
  padding-top: 15px;
  padding-bottom: 15px;
  margin-top: -15px;
  margin-bottom: -15px;
}

input type="checkbox"(このソースだと'.accordion-checkbox')は見た目上は必要ないので、display: noneで非表示にします。

トリガーとなるlabel.accordion-triggerはブロックにして、cursor: pointerを指定。

labelをクリックして、input type="checkbox"がcheckedになったら、その次の要素('.accordion-target')を展開するためのスタイルを指定します。('.accordion-checkbox:checked + から始まる部分')

CSSの指定のポイントは展開する要素の'ul.accordion-target'の子要素のスタイル、特にtransitionの指定が大事になってきます。

アコーディオンが閉じているスタイルをheight: 0、開いたときにheight: autoにすれば動きそうな気がしますが、この指定だと高さの取得がうまくいかず、意図した動きになりません。

そこで、子要素の高さを構成しているスタイルのプロパティ一つ一つにtransitonで値を指定していきます。ここを全要素指定 all 0.5s ease-outのようにしてしまうと、左右の余白などもアニメーションの対象になってしまうので、要注意です。

デモ GitHub

アコーディオン実装に関する記事

コメント

まだ、コメントはありません。

トラックバックURL

https://blog.pranktone.net/web/css/20191030171044.html/trackback
ありきたりな日常と
それとない非日常を
紡ぐ記録
SKIP