はてなブログでトップ位置固定のメニューを作成する
まず最初にお断りです。
これを実装するにはCSSやHTMLについて、そこそこの知識が必要です。
一番の注意点としてあげられるのは、はてなブログにはブログ最上部にグローバルヘッダ(DIV#globalheader-container)という、「Hatena Blog」って左側に書いてあるメニューバーがあって、これがデザインテーマによってpositionプロパティの指定が違うんですよ。position static;だったり、position fixed;だったり。
#わかりやすく言えば、スクロールさせたときにそのメニューバーが画面の外に消えるか、そのまま残るかってこと。それによって当然TOPプロパティの値を変える必要がある。
ちなみにこのブログのトップ位置固定メニューだって、このデザインテーマだとちゃんと表示されていますが、試しに他のデザインテーマに変えてみると、テーマによってはまともに表示されないものもあります。
全てはデザインテーマのCSS設定が違うことにあるんですね。
メニューの幅もエントリ領域(DIV#container)のmerginプロパティの値によってwidthプロパティの調整が必要だったり、単にコピペしただけではまともに表示されない可能性の方が高いです。
「メニューが片方に偏って表示される」「画面からはみ出してしまう」「スクロールさせたときに固定されず画面の外に出てしまう」など、いろいろ問題点が出てくると思うので、はっきりいって難易度は高いです。
あとこのメニューをちゃんと表示させるために「既存のcss設定値もいじることになる」場合もあるので、注意しないと元に戻せなくなる可能性もあります。
とにかく自分が満足できるようになるまでに、かなり手間がかかることは覚悟してください。
実はこのエントリ記事は、ずっと前にできてたんだけど、そういった理由もあって公開すべきかどうか迷ってたんだよね。
以前、紹介したはてなブログで位置固定のページトップボタンを設置するや、はてなブログのカテゴリ記事数によって、カテゴリ文字の大きさを変化させるみたいに、コピペすれば動くってものじゃなかったから。
だから「転んでも泣かない」っていう人じゃないとお勧めできないので注意してください。ここ重要なのでしっかり覚えておいてくださいね。
言い忘れてましたが、これの元ネタは「Webpark - ウェブサイト作成に役立つことをいろいろと」というブログを参考にさせてもらっています。このブログさんにはいろいろなcssテクニックが紹介されてて、しかも懇切丁寧な説明つきなのですごく参考になります。ぜひ訪れてみてください。
※注意:IEしか使ったことがない方はわからないと思いますが、他のモダンブラウザだとドロップダウンのサブメニューが、するっするっと降りてくる(言い方難しいな。なんて表現すればいいのだろう?)のですが、IEだとCSSのtransitionプロパティが効かないので、そのメニューが一瞬で表示されてしまいます。
このtransition効果の動きは自分は結構気に入っているのですが、IEだとそれをお見せできないのが非常に残念です。
HTMLの設定
ここからは上記で詳細させていただいたブログさんの2つのエントリ記事を組み合わせて作成しています。
・ドロップダウンメニュー作成時の参考リンク:CSSだけで作る動きのあるドロップダウンメニュー
→こちらが今回主に参考にしたリンク先です。
・位置固定メニュー作成時の参考リンク:上部固定メニューのお供に、jQueryを使ったクリックで開閉するメニュー
→こちらはメニュー部分のHTMLを参考にさせてもらっただけで、他はほとんど流用していません。
自分がオリジナルからいじったところは、はてなブログには「#globalheader-container」があるため、固定メニューのHTMLに加えjavascript(jQuery)を追加したところが大きな違いです。あとは色の指定など細かい部分だけで、その他はほとんど変わっていないので、詳細な説明はぜひ上記のリンク先を参照していただければ、と思います。
自分のヘボい説明(汗)より、ずっとずっとわかりやすい説明が載っています。
では、まずメニュー部分のhtmlとトップ位置固定するためのjavascript(jQuery)の全文です。
メニュー部分は各自変更してください。
これらを「デザイン」→「カスタマイズ」タブ→「ヘッダ」→「タイトル下」(HTMLを記述できます)へ、コピペしてください。
メニューカスタマイズの際の注意点としては、
- 子メニューの最後に「メニューを閉じる」をいうのを追加していますが、これはiPad対策のためです。iPadだとCSSのhover擬似クラスが効かなく、メニューをタップした後メニューが開きっぱなしになってしまうので、強制的にトップページを表示させることによってメニューを消してるという苦肉の策です。
- はてなブログの場合はたぶんないとは思いますが、もしかするとブログのhtmlソース上に#globalheader-containerがないものがあるかもしれません。その場合はglobalheaderPosition=0とデフォ設定した方がいいかも。その辺りは適宜判断してください。
- メニュー部分のHTMLを作る時の参考として、何でしたらこのブログのHTMLソースを見てもらえれば、より具体的な設定の仕方がわかってもらえると思います。
<div id="fixed-menu" class="absoltop"> <div id="fixed-menu-contents"> <ul id="dropmenu"> <li><a href="URL1">メニュータイトル1</a></li> <li><a href="URL2">メニュータイトル2</a></li> <li><a href="URL3">メニュータイトル3</a></li> <li><a href="#">メニュータイトル4</a> <ul> <li><a href="子URL1">子メニュー1</a></li> <li><a href="子URL2">子メニュー2</a></li> ・ ・ <li><a href="topページurl">メニューを閉じる</a></li> </ul> </li> <li><a href="#">メニュータイトル5</a> <ul> <li><a href="子URL1">子メニュー1</a></li> <li><a href="子URL2">子メニュー2</a></li> ・ ・ <li><a href="topページurl">メニューを閉じる</a></li> </ul> </li> </ul> </div> </div> <script> $(function() { var fixedmenu = $("#fixed-menu"); var fixedmenuTop = fixedmenu.offset().top; // 画面スクロール毎に判定を行う $(window).scroll(function() { //もし#globalheader-containerが存在しない場合は、以下3行を削除してglobalheaderPositionに0をデフォ設定してください。 var globalheadercontainer = $("#globalheader-container"); var globalheaderPosition = globalheadercontainer.offset().top; var globalheaderheight = globalheadercontainer.height() - 1; //#globalheader-containerのpositionプロパティ判定 static or fixed。 if (globalheaderPosition == 0) { // #globalheader-containerがposition: staticの場合 if ($(window).scrollTop() >= fixedmenuTop) { fixedmenu.addClass("fixedtop0"); } else { fixedmenu.removeClass("fixedtop0"); } } else { //#globalheader-containerがposition: fixedの場合 if ($(window).scrollTop() >= fixedmenuTop - globalheaderheight) { fixedmenu.addClass("fixedtop"); } else { fixedmenu.removeClass("fixedtop"); } } }); }); </script>
jQuery部分の補足説明
この部分は、はてなブログならではのオリジナルなので、説明を加えておきます。
ここでやっていることは3つです。
- #globalheader-container の位置取得(= globalheaderPosition変数)
- globalheaderPosition変数の値が、0ならstatic(固定なし)、1以上になればfixed(位置固定)と判断
- staticならばTOPプロパティに0pxを設定したクラス(fixedtop0)を、fixedならばTOPプロパティには37px(#globalheader-containerの高さ分)を設定したクラス(fixedtop)を、スクロールに合わせて追加したり、削除したりする(この「クラスの追加、削除」というのは、こういう位置固定手段の際のお約束のロジックですね)
使っているテーマの#globalheader-containerがstaticなのか、fixedなのか最初からわかっていれば、このif文は削除して片方のロジックだけにしてもらっても構いません。汎用性を持たせるためにこのif文を入れただけなので。
CSSの設定
次は「デザインCSS」の設定で、CSS定義のどこでもいいんですが以下をコピペしてください。
くれぐれも他のCSS定義は消さないようにね!
/* Top Menu */ #fixed-menu { width: 100%; max-width: 940px; padding: 0; z-index: 9999; /* background: #2e4153;*/ } .absoltop { position: absolute; top: 37px; } .fixedtop { position: fixed; top: 37px; } .fixedtop0 { position: fixed; top: 0px; } #dropmenu { list-style-type: none; width: 100%; height: 30px; margin: 0 auto 0 0; padding: 0; background: #56b5f0; border-bottom: 3px solid #0a4970; } #dropmenu li { position: relative; width: 20%; float: left; margin: 0; padding: 0; text-align: center; z-index: 9999; } #dropmenu li a { display: block; margin: 0; padding: 5px 0 11px; color: #fff; font-size: 16px; font-weight: bold; line-height: 1; text-decoration: none; } #dropmenu li:hover > a{ background: #1490dd; /* color: #a4d7f7; */ color: #ff0000; } #dropmenu > li:hover > a{ border-radius: 5px 5px 0 0; } #dropmenu li ul { position: absolute; top: 100%; left: 0; list-style: none; margin: 0; padding: 0; border-radius: 0 0 3px 3px; } #dropmenu li:last-child ul { left: -100%; width: 100% } #dropmenu li ul li { overflow: hidden; width: 200%; height: 0; color: #fff; -moz-transition: .2s; -webkit-transition: .2s; -o-transition: .2s; -ms-transition: .2s; transition: .2s; } #dropmenu li ul li a{ padding: 13px 15px; background: #1490dd; text-align: left; font-size: 16px; font-weight: normal; } #dropmenu li:hover ul li{ overflow: visible; height: 38px; border-top: 1px solid #56b5f0; -moz-transition: .4s ease .5s; -webkit-transition: .4s ease .5s; -o-transition: .4s ease .5s; -ms-transition: .4s ease .5s; transition: .4s ease .5s; border-bottom: 1px solid #616d0b; } #dropmenu li:hover ul li:first-child{ border-top: 0; } #dropmenu li:hover ul li:last-child{ border-bottom: 0; } #dropmenu li:hover ul li:last-child a{ border-radius: 0 0 5px 5px; }
CSSの補足説明
.absoltop { position: absolute; top: 37px; } .fixedtop { position: fixed; top: 37px; } .fixedtop0 { position: fixed; top: 0px; }
ここが、jQueryのロジックに関連して必要となったもので、オリジナルで追加した部分です。
デフォルトでは、#fixed-menuには、absoltopクラスが設定されていますが、jQueryによってスクロール位置を判断し、fixedtopクラスとfixedtop0クラスを使い分けて、追加したり、削除したりするのに使っています。
ちなみにわざわざabsoltopクラスを作っているのには理由があります。それは、はてなブログではHTMLを記述できる箇所が限定されているからなんですね。
試しに#fixed-menuからabsoltopクラスを削除してメニューを表示させると、そのメニューは「ブログタイトルの下」に表示されてしまいます。これはやってもらうとわかります。だからこのabsoltopクラスの指定が必要なのでした。
最後に
基本的には、メニュー部分さえちゃんと作ってしまえば、後は位置調整のためにpx指定をいじるくらいだとは思うのですが、最初にも書いたとおりCSS設定がデザインテーマによってまったく違うので、まずこれをコピペしてみて、まともに表示されればラッキー。
もしまともに表示されなければ、間違いなく既存のCSS設定値をいじる必要があって、しかもそれはデザインテーマによって、いじらなければならないところがまちまち。
どのプロパティをいじらなければならないのか?それをどうやってそれを調べるのか?など、問題は山積みだと思います。
#だから、コピペだけで動かなかったとして「どこが悪いんでしょうか?」という問い合わせをいただいたとしても、こちらとしてはそのデザインテーマのCSS設定値がわからないので、お答えしようがないのです・・・。かなり無責任な発言になってしまいますが、ご了承ください。
なので、ここから先はその人次第です。
「CSSなんてちょろいよ?」という方ならご自分のブログ用に余裕でカスタマイズできると思いますが、「CSSって何?」ってレベルだと、正直お勧めできません。
だから、いざというときに元に戻せるという自信がなければ、全部削除して諦めるか、
これも勉強のうちと思ってチャレンジするか。
自分は一応後者の方だったので、これを実装するには何度も試行錯誤を繰り返して、結構大変な思いをしました。
でもその甲斐あって満足できるものができましたけども。
自分もCSSのことはこのブログを始めるまでマジで知識0でしたけど、いろいろいじっているうちにだんだん理解できるようになったんですよね。
そうなると、やっぱりめちゃ楽しくなるんですよ。
自分が使っているデザインテーマで不満なところがあった場合に、どこを改善すればいいのかわかるようになるんだもの。
このメニューを作ったときにも新たなCSSの勉強もできたし、そうやって覚えたことを元にして、このデザインテーマをいろいろカスタマイズしてます。
#ちなみに、そのカスタマイズ内容も、後日別エントリ記事としてアップしようと思っています。
この固定メニューにチャレンジすることは、CSSを覚えるいい機会だと思うんですよね。
ぜひがんばってもらって、CSSに関する知識の量を増やしていただきたいな、と思っています。
【関連記事】
- 「プログラミング」カテゴリ一覧へ
【タグ】
{html}{css}