[css]アニメーションするハンバーガーメニュー例

どうだろう。

html

汎用性は求めてるけど。

<button type="button" data-btn="nav"><span></span></button>

遷移とかしないようにbutton:button。

ユニークにするためにidを振ってたけど、複数設置するケースを見越せばdata属性で管理したほうがいいように思う。classでもいいんだけど稀に被って干渉したりするし。
data属性だと処理が遅いだか重いだか言われたりもしてたんでどうなんでしょうね。

js(jQuery)

$(window).on('load resize',function(){
    if(window.matchMedia("(max-width: 767.98px)").matches){
    }else{
        $('button[data-btn="nav"]').removeClass('active');
        $('header nav').removeClass('active');
    }
})
$(function(){
    $('button[data-btn="nav"]').on('click',function(){
        $(this).toggleClass('active');
        $('header nav').toggleClass('active');
    })
})

表示・非表示はclass付与でやっていくと仮定する。

ついでにSP時のみハンバーガーメニューを表示するとして、PC・SPの切り替えはブラウザ幅判定のレスポンシブだとして、メニューが開きっぱなし(class付与した状態)でSP→PCになったら付与したclassを削除させる。

備考として.matchMedia()だけでもいいんだけど、たとえば<header>にclass=”sp”とかを付けてPC・SPを明確に切り替えるギミックを仕込んだ場合は.hasClass(‘sp’)を入れとくことで得することもある。

$(window).on('load resize',function(){
    if(window.matchMedia("(max-width: 767.98px)").matches){
        if(!$('header').hasClass('sp')){
            $('header').addClass('sp');
        }
    }else{
        if($('header').hasClass('sp')){
            $('button[data-btn="hnav"]').removeClass('active');
            $('header .nav').removeClass('active');
            $('header').removeClass('sp');
        }
    }
})

css(scss)

本題。

button{
    display: none;
    width: 60px;
    height: 60px;
    padding: 0;
    background: none;
    border: none;
    position: fixed;
    top: 0;
    right: 20px;
    z-index: 1;
    cursor: pointer;
    span{
        width: 40px;
        height: 2px;
        display: block;
        background: #111;
        position: absolute;
        left: 10px;
        top: calc(50% - 1px);
        transition: background 0s .2s;
        &::before,&::after{
            content: "";
            width: 100%;
            height: 100%;
            display: block;
            background: #111;
            position: absolute;
            z-index: 1;
        }
        &::before{
            top: -10px;
            transition: top .2s .2s ease, transform .2s 0s ease;
        }
        &::after{
            bottom: -10px;
            transition: bottom .2s .2s ease, transform .2s 0s ease;
        }
    }
    &.active{
        span{
            background: transparent;
            &::before{
                transform: rotate(45deg);
                top: 0;
                transition: top .2s 0s ease, transform .2s .2s ease;
            }
            &::after{
                transform: rotate(-45deg);
                bottom: 0;
                transition: bottom .2s 0s ease, transform .2s .2s ease;
            }
        }
    }
}

ポイントなのはtransition。
通常時と:hover時それぞれに仕込むことで、開閉それぞれで違う動作にすることができる。

アニメーション時間の指定だけでなくディレイも掛けられるんで、@keyframe的な仕込みができる。class付与時にtransform→top・bottomで動いて、class剥奪時にtop・bottom→transformで動く。3本線が重なった(1本になった)タイミングで中央の線を表示・非表示させることで洒落た感じになる。

まとめというか

作っておいて何なのだけど、buttonの中に空のspanをいれてるのが気に食わない。
HTMLだけで見たら無記入のbuttonが設置されているという気持ち悪い状態になる。

対策もあるんだけどさ。

<button type="button" data-btn="nav">
    <span class="icon"></span>
    <span class="text">menu</span>
</button>
button{
    display: none;
    width: 60px;
    height: 60px;
    padding: 0;
    background: none;
    border: none;
    position: fixed;
    top: 0;
    right: 20px;
    z-index: 1;
    cursor: pointer;
    span.text{ display:none;}
    span.icon{
        width: 40px;
        height: 2px;
        display: block;
        background: #111;
        position: absolute;
        left: 10px;
        top: calc(50% - 1px);
        transition: background 0s .2s;
        &::before,&::after{
            content: "";
            width: 100%;
            height: 100%;
            display: block;
            background: #111;
            position: absolute;
            z-index: 1;
        }
        &::before{
            top: -10px;
            transition: top .2s .2s ease, transform .2s 0s ease;
        }
        &::after{
            bottom: -10px;
            transition: bottom .2s .2s ease, transform .2s 0s ease;
        }
    }
    &.active{
        span.icon{
            background: transparent;
            &::before{
                transform: rotate(45deg);
                top: 0;
                transition: top .2s 0s ease, transform .2s .2s ease;
            }
            &::after{
                transform: rotate(-45deg);
                bottom: 0;
                transition: bottom .2s 0s ease, transform .2s .2s ease;
            }
        }
    }
}

ハンバーガーメニューが出てきた時期にはアホにはメニューアイコンって分からんだろってことでルビを振ることが正義みたいな事も言われてたけど、今はそれも収まってきてシンプルになってきた。
だから、「html上の書式」を気にする以上の意味合いが薄い。DOM要素を無駄に増やしても仕方ないし、書き込むなら活用しろよって気持ちもあるんだけど、シンプルが許されるから要らないわけで、とはいえルビを振りたいだけなら疑似要素を使えばopen/closeみたいな表示の切り替えがcss上で完結できるわけで、という。どうなんですかね。

コメント

タイトルとURLをコピーしました