jQuery・実務で必要な12項目をクリアしたレスポンシブドロワーメニューを作りました [IE11以上]
2017/09/24 縦スライドバージョンを作っておきました。CSS修正のみ。
2017/07/29 余計なCSSを削除し、jQueryの見直しを行いました。
2017/01/29 Mac OS・Safari限定でスクロール不可に。Mac版Safariはクソブラウザ化しているので放置。
※iOS、Androidは問題なし。
2015/10/16 発火後にリンクへ飛んでしまうバグを修正
2015年9月時点における、ドロワーメニューの実務要件を考えた。
- Android 4.1 で動作する
- PCのクリック / スマホのタップ、両方に対応
- スマホアプリのように滑らかにスライド
- スマホでタップすると、一瞬で開閉する
- オーバーレイをクリックで戻る
- 閉じるボタンも設置
- トリガーボタンを複数設置可
- オープン時、ドロワーメニュー部分のみスクロール ※コンテンツ側のスクロール無効
- ドロワーメニューの横幅をCSSで変更可 ※レスポンシブ
- viewport に余計なコードを追加しない
- 意味不明なHTML/CSSコードを追加しない
- jQuery 1.7.0~最新verまで対応
上記を満たした無料プラグインは、世界中のネットを探しても見当たらず。
それなら私が作ろうと。
IE10は対応しないの!?
1案件につき10万円追加してくれるなら、対応コードを作ります。
要点とコード
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="css/layout.css"> </head> <body> <div class="sd-trigger"> 開くボタン <!-- /.sd-trigger --></div> <nav id="sd-menu"> <ul> <li><a href="">HOME</a></li> <li><a href="">MENU</a></li> </ul> <span class="close">閉じるボタン</span> <!-- /#sd --></nav> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> <script src="js/smart-drawer.js"></script> </body> |
SCSS
- ドロワーメニュー・オーバーレイ共に position fixed で固定配置
- メニューは横幅マイナス値を left に指定し、左外側へ配置
- オーバーレイはwidth 100%、right -100% で右外側へ配置
- メニュー横幅は固定ピクセル・相対パーセントどちらでもOK
※レスポンシブでも固定ピクセルがベター - transform translate3d() でアプリ並みの滑らかさを実現
- スライド速度やイージングは transition で調整
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 89 90 91 92 93 94 95 96 97 | // ドロワーメニュー #sd-menu { width: 350px; height: 100%; color: white; overflow: auto; position: fixed; left: -350px; top: 0; z-index: 99; transition: transform 0.3s ease-out; background: #333; @include max(400) { width: 280px; left: -280px; } li { border-top: 1px solid lighten(#333, 5%); border-bottom: 1px solid darken(#333, 5%); &:first-child { border-top: 0; } } a { color: white; text-decoration: none; display: block; position: relative; padding: 5% 15% 5% 5%; &::after { @include arrow; width: 10px; height: 10px; top: 50%; right: 10%; margin-top: -2%; } } &.block { transform: translate3d(350px, 0, 0); @include max(400) { transform: translate3d(280px, 0, 0); } } // 閉じるボタン .close { text-align: center; cursor: pointer; display: block; position: relative; margin: 10% 5% 80%; padding: 5% 0; border: 1px solid darken(#333, 5%); &:after { content: ""; width: 100%; height: 100%; position: absolute; top: 0; left: 0; border: 1px solid lighten(#333, 5%); } } } // 開くボタン .sd-trigger { color: white; text-align: center; cursor: pointer; display: block; margin-bottom: 30px; background: #333; } // オーバーレイ #sd-overlay { width: 100%; height: 100%; position: fixed; right: -100%; top: 0; z-index: 9; transition: 0.3s; opacity: 0; background: rgba(0, 0, 0, 0.5); &.block { right: 0; opacity: 1; } } |
jQuery
完成コードはシンプルだが、制作過程は試行錯誤の連続…。
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 | /* Smart Drawer Author: KEITA HIRAI URL: keitahirai.net */ $(function() { // スクロール位置取得、タッチデバイス即発火用 var scrollY; // touch = ("ontouchstart" in document) ? "touchstart" : "click", $("body").append('<div id="sd-overlay"></div>'); // ドロワーメニューとオーバーレイ var sd = $("#sd-menu"), overlay = $("#sd-overlay"); // 開くボタン // $(".sd-trigger").on(touch, function(e) { $(".sd-trigger").click(function(e) { scrollY = $(window).scrollTop(); $("body").css({ position: "fixed", top: -scrollY }); sd.addClass("block"); overlay.addClass("block"); e.preventDefault(); return false; }); // 閉じるボタンとオーバーレイ両方で閉じる // $("#sd-menu .close, #sd-overlay").on(touch, function(e) { $("#sd-menu .close, #sd-overlay").click(function(e) { $("body").attr("style", ""); $("html, body").prop({scrollTop: scrollY}); sd.removeClass("block"); overlay.removeClass("block"); e.preventDefault(); return false; }); }); |
ハマった箇所
Chromeでメニューのスクロールがフリーズ
translateX() を translate3d() に変更したら直った。
なぜ3dにする必要があるのかは不明。
Android 5でオーバーレイをタップできない
画面外側へ配置せず、transitionで透明度を0 -> 1に変化させるのみだと、なぜかタップできなくなる。
従って、右外側へ配置したスライド式に変更。
カスタマイズ
- メニューを右からスライドさせたい
- left を right に修正し右側へ配置、translate3d() でマイナスを指定。1234567891011121314#sd-menu {right: -350px;@include max(400) {right: -280px;}&.block {transform: translate3d(-350px, 0, 0);@include max(400) {transform: translate3d(-280px, 0, 0);}}}
- メニュー横幅を固定ピクセルでなく相対パーセントにしたい
- CSSを修正すればOK。
posted with amazlet at 15.09.01
古籏 一浩
シーアンドアール研究所
売り上げランキング: 337,626
シーアンドアール研究所
売り上げランキング: 337,626
4コメント
こんにちは。こちらのドロワーメニューはシンプルで使い勝手がとても良く、大変ありがたく利用させていただいております。
ページ内リンクやリンク先ページのアンカー項目に飛ばしたい場面があるのですが、URLにアンカーがあると遷移しないようです。
アンカーには対応できないでしょうか。
可能であれば、ご教示いただきたく、何卒お願い申し上げます。
すーじーさん
こんばんは。当ブログ管理人の平井です。
自作ドロワーメニューを使って頂きとても嬉しいです。
明日検証してみますので、回答までもうしばらくお待ちください。
返信が遅れすみません。
ページ遷移してアンカーへ飛ばすのを試してみたところ、問題なく動作しました。
例えば下層ページ second.html の #block2 に飛ばしたいときは、
a href=”second.html#block2″
で動作します。
ページ内リンクのアンカーへ飛ばすには、ページ固定とスクロール位置保持を解除すると可能です。
以下のように、22行目と36行目をコメントアウトで無効化してみてください。
// position: “fixed”,
// $(“html, body”).prop({scrollTop: scrollY});
ただこれを実行すると、ドロワーメニューを開いた時にブラウザスクロールは固定されなくなります。
その点も含め一度試してみてください。
無事ページ内リンクへ飛ばすことができました。
お手数をおかけし申し訳ありませんでした。
これでさらに実務で使い勝手が良くなり嬉しいです。
素早いご対応ありがとうございました!