cssだけでドロップダウンメニューを実装する

cssだけでドロップダウンメニューを実装しようとして、色々ググったが、やり方がやたら複雑だったので、ここにメモ。

ということで、まずは完成形。

そして、完成形のコード。

<ul class="basic-menu-list">
    <li class="basic-menu-item">
        <span href="#" class="basic-menu-link">ここがドロップダウンだよ</span>
        <ul class="child-menu">
            <li class="basic-menu-item"><a href="#">マイページ</a></li>
            <li class="basic-menu-item"><a href="#">ログイン</a></li>
            <li class="basic-menu-item"><a href="#">ログアウト</a></li>
        </ul>
    </li>
</ul>
/*drop-down-menu*/
ul {
    list-style: none;
}
a {
    text-decoration: none;
}
.basic-menu-list {
    border: 2px solid #f00;
}
/*通常は非表示*/
ul.child-menu {
    display: none;
    opacity: 0;
}
/*表示に切り替え*/
li.basic-menu-item:hover ul.child-menu {
    display: block;
    animation: show 2s;
    opacity: 1;

}
/*アニメーション*/
@keyframes show{
    from{
        opacity: 0;
    }
    to{
        opacity: 1;
    }
}





実装方法はシンプルで、通常はdisplay: none;で非表示にしておき、カーソルが重なったことをダイナミック擬似クラスである:hoverで検知して、display: block;で表示させるという方法。

display: none;ではなく、visibility: hiddenを使って非表示することもできますが、この場合だとレイアウト自体には要素が存在しているため、余計な空白ができてしまいます。display: none;だと、要素を不可視にして、レイアウトから除外することができます。

参考 developer.mozilla

注意したいのがdisplay: none;にアニメーションをつける方法です。以下のようだと動きません。

/*通常は非表示*/
ul.child-menu {
    display: none;
    opacity: 0;
    transition: opacity 1s;
}
/*表示に切り替え*/
li.basic-menu-item:hover ul.child-menu {
    display: block;
    opacity: 1;
}

transitionプロパティを利用すると、始点と終点の2点間のアニメーションを作成することができますが、この場合だとdisplay: block;のタイミングでDOMが生成されるため、transitionプロパティの始点がない状態になります。

プロパティ 作成できるアニメーション
transition 始点と終点の2点間のアニメーション





という訳で、ここではanimationプロパティを使います。

プロパティ 作成できるアニメーション
animation キーフレームを利用したアニメーション





/*アニメーション*/
@keyframes show{
    from{
        opacity: 0;
    }
    to{
        opacity: 1;
    }
}





See Also