それでは「document.getElementById」のID取得メソッドと「addEventListener」のイベント処理のメソッドを使って、WEBサイトでよく見かける、ボタンをクリックすれば下記のような横からにゅっと出現するメニューバーを作成してみます。
おおまかな作成の手順としては下記の感じです。
・HTMLにイベントのトリガーとなるボタンを配置
・HTMLにメニューとなる要素を配置
・CSSでメニューの閉じた状態と開いた状態をスタイリング
・javascriptにイベント処理を記述
あらかじめメニューは閉じた状態にしておいて、イベント発生時にメニューが開くようにCSSの「class」を変更させる所がポイントです。
ファイル構成は下記の通りとします。(cssとjsのテキストは各ディレクトリ内に作成)
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>メニュー</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <header><h1>Hallo!</h1> <p id="menu">menu</p> <nav id="nav" class="navi"> <ul> <li><a href="#">オアシス</a></li> <li><a href="#">レディオヘッド</a></li> <li><a href="#">虎舞竜</a></li> </ul> </nav> <div id="back" class="menu-background"></div> </header> <warapper> <main>main </main> <side>side </side> </warapper> <footer>footer </footer> <script src="js/main.js"></script> </body> </html> |
headタグ内は文字コード、レスポンシブ、タイトル、cssの読み込み先を記述しています。いつも通りですね。
mainタグ以降は、各要素適当に名前を入れているだけにしました。
scriptタグは外部scriptとし、body閉じタグ直前にjavascriptのファイル指定先を記述しています。
肝心のメニューについてですが、今回はheader要素内に記述しています。
まず、h1タグはWEBサイトのロゴとします。
その横に、pタグでidを付けた「menu」の文字を配置し、これをイベント発生用のボタンとします。(3本線のアイコンにしたい場合は、別途DLしたりしてください。)
続いてのnav要素が、今回横から出てくるメニューになります。あとで開閉時の状態をCSSでスタイリングするので、IDとclassを付けておきます。
ul、liタグについては、とりあえず適当にしておきます。(次回、アコーディオンメニューします。)
最後に空のdiv要素を作り、idとclassを付けておきます。これはメニューが開いた時の背景(main画面の方)を表す要素にします。半分開いたら残りのメイン画面が薄暗くなるやつです。
css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
body { margin: 0; padding: 0; } header { background:skyblue; display: flex; } header h1 { padding-left: 20px; } header p { margin-left: auto; cursor: pointer; line-height: 46px; padding-right: 20px; z-index: 150; } .navi { background: #0bd; position: fixed; overflow: hidden; top: 0; bottom: 0; right: 0; text-align: center; width: 0; transition: 0.2s; z-index: 100; } .open-menu { width: 50%; } nav ul { padding: 50px 20px; } nav li { list-style: none; text-align: left; padding: 10px 0; } nav li a { display: block; } .menu-background { position: fixed; top: 0; right: 0; display: block; width: 0; height: 0; background: black; opacity: 0.8; } .open { width: 100%; height: 100%; } main { background:orange; } side { background: pink; display: block; } footer { background: green; } @media screen and (min-width: 600px) { header p { display: none; } body { max-width: 1000px; } warapper { display: flex; width: 100%; } main { width: 70%; } side { width: 30%; } } |
主要な部分に絞って説明します。
headerのdisplay:flexで、h1のサイトロゴとp要素のmenuボタンをインラインで並べます。marginで左右に配置しています。menuのp要素にz-indexを付けているのは、メニューが出てきたときに下に埋もれないために高さを付けています。
menuは、縦幅は画面全体、右から横幅は50%で出し入れさせようと思います。
したがって、menu要素になるnavi classに、position:fixed;でtop:0;bottom:0;right:0;にすれば、あとはwidthの値で横幅を決定できるので、50%にすればOKです。transitionを設定すれば、ぬるっと右側から出てきます。あとは、z-indexで高さをつけてやります。(後述するバック画面より高くする必要がある。)
ただし、平常時は隠しておかないといけませんので、widthを0にしておきます。overflow:hidden;は、テキストを消すための記述です。
ここがポイント。
その後のopen-menu classで、width:50%;を設定していますので、つまりイベント処理でもともとのnav idに付随しているnavi classからopen-menu classへ変更(厳密に言えば追加)してやればいいのです。
menuのopen時、close時のclassを作っておいて、平常時はcloseのclassをあてておく、という事ですね。
あとはjavascriptに任せます。
menu画面が出た際に、残り半分の画面を薄暗く設定してやります。
id backに付随しているmenu-background classにposition:fixed;top:0;right:0;としてやって、widthとhightを0にしておきます。
これで平常時は見えません。あとはbackground:black;でopacity:0.8;で薄暗く表示するように設定しておきます。
これもopen classにwidth:100%;hight:100%;を設定しているので、イベント処理でclass変更(追加)をかければ、画面全体が薄暗くなります。ただし、menu要素より高さを低くする必要があります。(menuも暗くなってしまう。)
その他もろもろ
あとはレスポンシブ対応とかその辺りを記述しています。
一応、600px以上なら、menu表示が出ないような設定にしています。
カラムも、600px以上なら2カラムにしています。
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const menu = document.getElementById("menu"); const back = document.getElementById("back"); const nav = document.getElementById("nav"); menu.addEventListener("click", () => { if (nav.className === "navi") { nav.classList.add("open-menu"); back.classList.add("open"); menu.textContent = "閉じる"; }else {nav.classList.remove("open-menu"); back.classList.remove("open"); menu.textContent = "menu"; } }); back.addEventListener("click", () => { back.classList.remove("open"); nav.classList.remove("open-menu"); menu.textContent = "menu"; }); |
初めに、menu id(イベントボタン要素),back id(ナビメニューの裏側の要素),nav id(ナビメニューの要素)、それぞれのIDを取得し、定数に代入します。
上段のイベント処理は、アロー関数の中にif文が入っています。
menuをクリックした時、nav IDのclassが「navi」(初期状態)なら真の処理、「open-menu」を追加します。これでmenuが開きます。
同時に、back IDのclassに「open」を追加するので、メニュー以外の部分が薄暗くなり、menuのテキストが「閉じる」に変わります。
つまり、メニューを開く動作になります。
nav IDのclassが「navi」でなければ(メニューが開いている状態)、偽の処理となり、remove()でカッコ内のclassが解除されます。
つまり、閉じる動作となり、真とは逆の動作となります。
下段のイベント処理は、back ID、つまり、メニューが開いているときの薄暗くなっている箇所をクリックしたときの動作になります。
上段のelseと同じイベントとなっているので、薄暗くなっている箇所をクリックすればメニューを閉じる動作を発生させています。
以上で、冒頭の横からにゅっと出てくるメニューの実装が出来ます。
記述はもっとスマートに出来るはずですが、このように単純な記述だけでも実装できることが分かります。
それでは、次回はメニューバーに「アコーディオンメニュー」を実装してみようと思います。