要素の高さを取得してアコーディオンのレスポンシブ化を実装してみた

Keisuke Ota

アコーディオンの実装方法とレスポンシブ化について、できるだけわかりやすくなるように図を交えながら説明します。

目次 [表示する]

  1. アコーディオンの実装
    1. 完成形
    2. アコーディオン実装の考え方
  2. アコーディオンのレスポンシブ化
    1. 子要素の高さを取得
    2. hoverイベントによる”height: auto;”の切り替え

アコーディオンの実装

完成形

説明は後でいいから、見本となるコードを早く教えてほしいという方がいるかもしれないので

まず最初に完成形となるコードを張り付けておきます。

jQuery

                            
$(function() {
    $('.box1').click(function() {
        if ($('.accordion-wrapper').hasClass('open')) {
            $('.accordion-wrapper').removeClass('open');
            $('.accordion-wrapper').css('height', $('.box1').innerHeight());
        } else {
            $('.accordion-wrapper').addClass('open');
            $('.accordion-wrapper').css('height', $('.box1').innerHeight() + $('.box2').innerHeight());
        }
    });

    $('.box1').hover(function() {
        if ($('.accordion-wrapper').hasClass('open')) {
            $('.accordion-wrapper').css('height', $('.box1').innerHeight() + $('.box2').innerHeight());
        }
    }, function() {
        if ($('.accordion-wrapper').hasClass('open')) {
            $('.accordion-wrapper').css('height', 'auto');
        }
    });
});
                            
                        

HTML

                            
<div class="accordion-wrapper">
    <div class="box1">開閉ボタン</div>
    <ul class="box2">
        <li class="menulist">メニューリスト1</li>
        <li class="menulist">メニューリスト2</li>
        <li class="menulist">メニューリスト3</li>
    </ul>
</div>
                            
                        

CSS

                            
.accordion-wrapper {
    width: 250px;
    margin: 0 auto;
    text-align: center;
    font-size: 16px;
    line-height: 1.5;
    transition: 0.3s;
    height 40px;
    overflow-y: hidden;
}
.accordion-wrapper .box1 {
    background: #019286;
    padding: 8px;
    color: #fff;
    cursor: pointer;
}
.accordion-wrapper .box2 {
    background: #84e9e0;
}
.accordion-wrapper .box2 .menulist {
    padding: 8px;
}
                            
                        

上記を実装したものがこちらです。

開閉ボタン

アコーディオン実装の考え方

それでは順に説明していきます。

まずは、ボックスを二つ用意します。

  • box1:”開く”と”閉じる”を切り替えるためのボタン
  • box2:開いたり閉じたりする要素

HTML

                            
<div class="accordion-wrapper">
    <div class="box1">開閉ボタン</div>
    <ul class="box2">
        <li class="menulist">メニューリスト1</li>
        <li class="menulist">メニューリスト2</li>
        <li class="menulist">メニューリスト3</li>
    </ul>
</div>
                            
                        

CSS

                            
.accordion-wrapper {
    width: 250px;
    margin: 0 auto;
    text-align: center;
    font-size: 16px;
    line-height: 1.5;
    transition: 0.3s;
}
.accordion-wrapper .box1 {
    background: #019286;
    padding: 8px;
    color: #fff;
    cursor: pointer;
}
.accordion-wrapper .box2 {
    background: #84e9e0;
}
.accordion-wrapper .box2 .menulist {
    padding: 8px;
}
                            
                        

開いた状態の高さと、閉じた状態の高さを測ります。

今回は、開いた状態が160px、閉じた状態が40pxとなるため、cssへ、次のように追記します。

CSS

                            
.accordion-wrapper {
    width: 250px;
    margin: 0 auto;
    text-align: center;
    font-size: 16px;
    line-height: 1.5;
    transition: 0.3s;
    height 40px; //追記(閉じた状態の高さ)
    overflow-y hidden; //追記
}
.accordion-wrapper.open {
    height 160px; //追記(開いた状態の高さ)
}
~ 以下略 ~
                            
                        

ここで重要なのが、overflow-y: hidden;です。これを高さの指定とセットで使用することにより、指定した高さ以上の表示がされなくなります。

開いたときのみ、親要素に”open”というクラスがつくように、jQueryで処理を実装すればアコーディオンの出来上がりです。

jQuery

                            
$(function() {
    $('.box1').click(function() {
        if ($('.accordion-wrapper').hasClass('open')) {
            $('.accordion-wrapper').removeClass('open');
        } else {
            $('.accordion-wrapper').addClass('open');
        }
    });
});
                            
                        

アコーディオンのレスポンシブ化

アコーディオンのレスポンシブ化には、”innerHight()”による要素の高さを取得およびhoverイベントによる”height: auto;”の切り替えを行います。

子要素の高さを取得

今回のタイトルにあるように、アコーディオンに対するレスポンシブ化を実装していきたいと思います。

レスポンシブ化により、表示幅が小さくなったときにどんな問題が起きるかというと、

次のように、文字が改行されてしまって、子要素の高さが変化してしまうという問題が起きてしまいます。

そうでなくとも、PC表示用とスマホ表示用で中身のレイアウトを大きく変えたいなんてこともありますよね

こうなると、全体の高さが指定した高さと一致しなくなるため、要素が途中で途切れてしまうなどの事象が発生してしまいます。

そうならないために、jQueryで子要素の高さを取得して、それを全体の高さに反映するようにします。

それではさっそく実装していきましょう。

jQuery

                            
$(function() {
    $('.box1').click(function() {
        if ($('.accordion-wrapper').hasClass('open')) {
            $('.accordion-wrapper').removeClass('open');
            $('.accordion-wrapper').css('height', $('.box1').innerHeight());
        } else {
            $('.accordion-wrapper').addClass('open');
            $('.accordion-wrapper').css('height', $('.box1').innerHeight() + $('.box2').innerHeight());
        }
    });
});
                            
                        

“innerHight()”は、要素の高さを取得するための関数です。

hoverイベントによる”height: auto;”の切り替え

細かいですが、開いたままの状態で子要素の高さが変わると、全体の高さは一定のままのため、表示が途切れてしまいます。

“height: auto;”としてあげないと、要素の高さに応じて適切な高さに変化しません。

しかし、”height: auto;”に設定してしまうと、”transition”によるアニメーションが機能しません。

そのため、クリックの直前にのみ、”height: auto;”ではなく高さを指定する必要があります。

クリックの直前には、確実に要素がhoverされるので、このタイミングで高さを指定してあげます。開いた状態かつhoverが外れたときは、”height: auto;”になるようにjQueryで実装してあげれば無事に解決します。

それが冒頭にも提示したこちらになります。

jQuery

                            
$(function() {
    $('.box1').click(function() {
        if ($('.accordion-wrapper').hasClass('open')) {
            $('.accordion-wrapper').removeClass('open');
            $('.accordion-wrapper').css('height', $('.box1').innerHeight());
        } else {
            $('.accordion-wrapper').addClass('open');
            $('.accordion-wrapper').css('height', $('.box1').innerHeight() + $('.box2').innerHeight());
        }
    });

    $('.box1').hover(function() {
        if ($('.accordion-wrapper').hasClass('open')) {
            $('.accordion-wrapper').css('height', $('.box1').innerHeight() + $('.box2').innerHeight());
        }
    }, function() {
        if ($('.accordion-wrapper').hasClass('open')) {
            $('.accordion-wrapper').css('height', 'auto');
        }
    });
});
                            
                        

HTML

                            
<div class="accordion-wrapper">
    <div class="box1">開閉ボタン</div>
    <ul class="box2">
        <li class="menulist">メニューリスト1</li>
        <li class="menulist">メニューリスト2</li>
        <li class="menulist">メニューリスト3</li>
    </ul>
</div>
                            
                        

CSS

                            
.accordion-wrapper {
    width: 250px;
    margin: 0 auto;
    text-align: center;
    font-size: 16px;
    line-height: 1.5;
    transition: 0.3s;
    height 40px;
    overflow-y: hidden;
}
.accordion-wrapper .box1 {
    background: #019286;
    padding: 8px;
    color: #fff;
    cursor: pointer;
}
.accordion-wrapper .box2 {
    background: #84e9e0;
}
.accordion-wrapper .box2 .menulist {
    padding: 8px;
}
                            
                        

これで、表示幅の違いによって子要素の高さが変化してもレイアウトが崩れることのないアコーディオンを実装することができました。

上記を実装したものがこちらです。

開閉ボタン

Related