ハンバーガーメニューのアニメーション
覚書。
コードと結果
See the Pen by MarumiMusic (@marumimusic) on CodePen.
このコードに至るまで
初めはアイコンを動かす予定でなかったので、擬似要素でicon表示してました。
<div id="nav-var"> <input type="checkbox" value="off" id="nav-item"> <label id="nav-icon" for="nav-item"></label> <label id="nav-bg" for="nav-item"></label> <div id="nav-item-inner"> <ul> <li><a href="#">MENU1</a></li> <li><a href="#">MENU2</a></li> <li><a href="#">MENU3</a></li> <li><a href="#">MENU4</a></li> <li><a href="#">MENU5</a></li> </ul> </div> </div>
labelに擬似要素でfontawesomeなどでアイコンをもってきて三本線を表示してました。
修正後
アニメーションしたい時は
<div id="nav-var"> <input type="checkbox" value="off" id="nav-item"> <label id="nav-icon" for="nav-item"> <span></span> <span></span> <span></span> </label> <label id="nav-bg" for="nav-item"></label> <div id="nav-item-inner"> <ul> <li><a href="#">MENU1</a></li> <li><a href="#">MENU2</a></li> <li><a href="#">MENU3</a></li> <li><a href="#">MENU4</a></li> <li><a href="#">MENU5</a></li> </ul> </div> </div>
とspanタグで線を作るのがよく見かけた方法でした。
解説
spanタグで線を作る。
nth-child(2)で二本目の線の上下にマージンをいれる。
transformで回転。
で、最初の結果に。
線についての追記
spanタグで線を作る時、背景の正方形のど真ん中に表示するための計算がややこしく感じた。 初心者の私はこれがよくわかっておらず、計算方法をいろいろ確かめた。
結果、こちら。
1. アイコン全体のサイズを決める
$nav-menu-icon-size: 50px; //navメニューのiconサイズ #nav-icon{ width: $nav-menu-icon-size; height: $nav-menu-icon-size; line-height: $nav-menu-icon-size; }
これで50pxの正方形ができた。
2. アイコンの線の太さを決める
$nav-menu-icon-line: 3px; //アイコンの線の太さ #nav-icon span { height: $nav-menu-icon-line; }
これでハンバーガーメニューの三本線の太さが決まった。
3. 真ん中の線の上下余白を決める
$nav-menu-icon-middle-line-margin: 5px; //真ん中の線の上下余白 #nav-icon span:nth-child(2) { margin: #{$nav-menu-icon-middle-line-margin} auto; }
これで真ん中の線と上下の線の間に余白が5pxできた。
margin:#{$nav~} auto
としているのは、左右の余白をオートにして真ん中寄せにするため。
4. アイコン上下の余白を計算する
まずは三本線太さ+真ん中線の上下余白を計算。
$nav-menu-icon-line-all-height:((3px * 3) + (5px * 2)); //アイコンの線太さ分 + 真ん中の線上下余白分
三本線の太さ(3pxが3つ)と真ん中の線の上下余白(5pxづつ)のサイズを足す。
この時点で三本線は、アイコンの背景である50pxの正方形の上によってしまい、上下に余白がない状態なので、その余白分を計算する必要がある。
$nav-menu-icon-margin: calc((#{$nav-menu-icon-size} - #{$nav-menu-icon-line-all-height}) / 2); //アイコンの上下マージン #nav-icon span:first-child { margin-top: $nav-menu-icon-margin; } #nav-icon span:last-child { margin-bottom: $nav-menu-icon-margin; }
背景の50px正方形の高さ-三本線の太さ(余白も含む)を足し、上下の余白を割り出す。
その後2分割し均等に上下に余白が入るよう計算する。
1本目のmargin-top
と3本目のmargin-bottom
にそれぞれ余白を入れる。
5. 結果
#nav-icon span { display: block; background-color: #ffffff; //線の色 width: 21px; //線の横幅 height: $nav-menu-icon-line; //線の縦幅 border-radius: 2px; //ちょっと丸くする margin: 0 auto; //真ん中に寄せる transition: transform 0.3s ease, width 0.3s ease; &:nth-child(2) { margin: #{$nav-menu-icon-middle-line-margin} auto; } &:first-child { margin-top: $nav-menu-icon-margin; } &:last-child { margin-bottom: $nav-menu-icon-margin; } }
これでど真ん中に線が配置された。 線自体の太さや、余白をかえるときは変数を変えて調整すればOK。
アニメーションについての追記
spanタグで線を作る時、線の長さや太さ・余白が変わればもちろんtransformのtranslateの値も変わる。
計算方法
単純に、三本線から×になるとき、真ん中の線を消すので、その分をtranslateで上下線をそれぞれ動かしてやれば良い。
//==変数==// $nav-menu-icon-line: 3px; //アイコンの線の太さ $nav-menu-icon-middle-line-margin: 5px; //真ん中の線の上下余白 //==計算==// $nav-menu-icon-translate: $nav-menu-icon-line + $nav-menu-icon-middle-line-margin; //真ん中の線の太さ+余白分 //==SCSS==// #nav-icon #nav-item:checked ~ #nav-icon span { &:first-child { transform: translateY($nav-menu-icon-translate) rotateZ(45deg); //真ん中の線が消えた分をtranslateYで調整 } &:nth-child(2) { width: 0; //真ん中の線は消す } &:last-child { transform: translateY(-$nav-menu-icon-translate) rotateZ(-45deg); //真ん中の線が消えた分をtranslateYで調整 } }
最後に
ねっからの文系である私は計算がめちゃくちゃ苦手なので、自分がまたやるときにわけわかめになっていると想定して記事にしてみた。
きっと理数系の方にはちょちょいのちょいな計算なのであろうと思う。すごく羨ましい。
もっと簡単に計算できる方法や考え方があれば是非ご教授お願いいたします…!(T0T)