【CSS】ページトップボタンの配置:6パターン
ページトップボタンを配置する方法(位置)として、6つのパターンを紹介します。
JavaScriptは使わず、(HTMLと)CSSのみで実装します。
冒頭からクソ長いお気持ち表明を書いてしまったので、結論だけ知りたい人は下のcodepenの埋め込みまでスクロールしてください。
目次
はじめに
最近のWebサイトでは、ページの最上部(トップ)へ戻るためのボタンが、ウインドウ右下に設置されているのをよく見かけます。
その配置にはいくつかの方法が考えられます。
ひとつは、最も単純なもので、コンテンツの最下部やフッターの中に置かれているだけのものです。
しかし、このタイプはページを一番下までスクロールしないとボタンが現れず、ページの途中でトップに戻ろうと思ってもボタンを押せません。
そこで考えられたのが position: fixed;
を用いることで、スクロールに関わらずボタンをウインドウ右下に常に固定しておく方法です。
実際この方法でページトップボタンを設置しているサイトがほとんどかと思われますが、少し安直な気がします。
まず、幅の狭いモバイル向けサイトや、コンテンツをウインドウの端まで目一杯広げるLPサイトのようなサイトでない限り、「メインコンテンツの幅=ウインドウの幅」ではないはずです。
実際、LPでない普通のPC向けサイトでは、コンテンツの幅にmax-width
を設定して中央寄せしているサイトが大半かと思います。
このような場合に、メインコンテンツの位置に関わらずウインドウ基準でページトップボタンを設置してしまうと、コンテンツとボタンが離れ過ぎてダサい、あるいはボタンが押しづらいなどと感じるかも知れません。
つまり、言いたいことは、ページトップボタンを固定する位置は「ウインドウの端」ではなく、「コンテンツの端」にすべきということです。
先にも述べたように、これが問題となるのは「コンテンツ幅=ウインドウ幅」であるモバイルサイトやLPサイトではなく、「コンテンツ幅<ウインドウ幅」が顕著になるPC向けサイトにおいてです。
はじめに、ウインドウ基準でボタンを固定するのは「安直」と書きましたが、実際、コンテンツ基準でボタンを固定するためには少し頭を使わなければなりません。
また、モバイルサイトでは仕方がないものの、コンテンツ内にページトップボタンを固定配置すると、コンテンツ要素とボタンが被ってしまって見づらいという問題もあります。
そこでウインドウ幅に余裕があるような場合では、コンテンツ内の右端にボタンを設置するのではなく、コンテンツの「外側」にボタンを配置するのが最もよいのではないかと提案します。
前置きが長くなりましたが、この記事で紹介する6パターンのうち、3つのパターンとは既に出てきた以下の配置場所のことです:
- ウインドウ右下にボタンを固定(安直)
- コンテンツ内の右下に固定
- コンテンツ右下の外側に固定
そして残りの3パターンは上記の配置に、コンテンツの後に来るフッターとページトップボタンが被らないようにするという条件を加えたものです。
これは需要があるのかいまいちわかりませんが、なんとなくその実装方法をググってみると、どの記事でもJavaScriptを用いた方法でしか紹介されていなかったので、私が発明?したCSSのみで実装できる方法を上の3パターンそれぞれに対して紹介しようと思います。
ある程度のHTMLテンプレートは仮定してしまいますが、大体のサイトは同じようなテンプレートに従っているので多分大丈夫かと思います。
それでは早速、ページトップボタン固定のテンプレートを見ていきましょう。
ベースとなるHTML、CSS
以下のような構造のHTMLに、ページトップボタンを挿入したいと思います。
<body> <header> <div class="wrapper"> ヘッダー </div> </header> <div class="content"> <div class="wrapper"> <main>メイン</main> <aside>サイド</aside> </div> </div> <footer> <div class="wrapper"> フッター </div> </footer> </body>
CSSは以下の通り。
.wrapper { max-width: 500px; margin: 0 auto; } .content .wrapper { display: flex; } main { min-height: 120vh; flex-grow: 1; }
.wrapper
でmax-width
を設定し、中身を中央寄せしています。
また、.content
内の.wrapper
にdisplay: flex;
を設定し、main
とaside
を横並びにしています。
main
のmin-height
はとりあえずページをスクロールできるようにするために書いただけで、flex-grow: 1;
は幅いっぱいに広げるための記述です。
このテンプレートに、以下でページトップボタンを挿入していきます。
position: fixed
はじめに完成品のサンプルをまとめて与えておきます。
See the Pen fixed to-pagetop button by nakasu (@nakasu) on CodePen.
上記のサンプルコードを、以下で解説していきます。
1. ウインドウ右下にボタンを固定
最も簡単な、ウインドウ右端にボタンを固定する方法です。
ますは、どこでもいいですが、例えば</footer>
の下に以下のコードを追加します。
<div class="to-pagetop"> <a href="#" class="btn">ページトップへ</a> </div>
CSSは次のように指定します。
.to-pagetop .btn { position: fixed; right: 20px; bottom: 20px; }
ページトップボタン.btn
を、position: fixed;
でウインドウ基準で固定します。
right
とbottom
で固定する位置を指定します。
right
とbottom
を0
にして、margin
やpadding
で位置を調整しても構いません。
2. コンテンツ内の右下にボタンを固定
.wrapper
の中にボタンを入れることで、ウインドウの右端ではなくコンテンツの右端にボタンを固定します。
例えば、</footer>
の下に以下のコードを追加します。
<div class="to-pagetop"> <div class="wrapper"> <a href="#" class="btn">ページトップへ</a> </div> </div>
CSSは次のように指定します。
.to-pagetop { width: 100%; position: fixed; bottom: 0; } .to-pagetop .wrapper { position: relative; } .to-pagetop .btn { position: absolute; bottom: 20px; right: 20px; }
まず.to-pagetop
ウインドウ最下部にfixed
します。
このときfixed
した要素の幅はauto
のように振る舞ってしまうので、改めてwidth: 100%;
を指定します。
コンテンツの幅を利用するために.wrapper
の中にボタンを入れますが、.wrapper
にはposition: relative;
を設定しておきます。
そうすることで、ボタンの位置を親要素.wrapper
からの相対位置で指定できるようになります。
3. コンテンツ右下の外側にボタンを固定
コンテンツの右端の外側にボタンを固定します。
</footer>
の後にボタンを追加します。
<div class="to-pagetop"> <div class="wrapper"></div> <div class="btn-wrapper"> <a href="#" class="btn">ページトップへ</a> </div> </div>
CSSは次のように指定します。
.to-pagetop { display: flex; justify-content: center; } .to-pagetop .wrapper { margin: 0; flex-grow: 1; } .to-pagetop .btn { position: fixed; bottom: 20px; margin-left: 20px; }
まずは.to-pagetop
にflex
を設定することで、その子要素である.wrapper
と.btn-wrapper
を横並びで中央寄せします。
.wrapper
の中には何も入ってませんが、これは.wrapper
に設定された幅(=コンテンツの幅)を利用しているだけです。
また、.wrapper
には中央寄せをするために左右のmargin
をauto
に設定していましたが、これが邪魔になってくるのでmargin: 0;
でキャンセルします。
この作業が面倒に感じるなら、(.wrapper
に設定していた)コンテンツの幅を変数にして覚えておいて、上のHTMLで.wrapper
としているところを適当な要素に変更して、それに覚えておいたコンテンツ幅を設定するだけでもよいです。
あるいは、元からwrapper
の中央寄せをmargin: auto
ではなくて親要素のflex
で行っていてもよいです。
また、.wrapper
にflex-grow: 1;
を設定していますが、これはmax-width
で設定した値まで幅を大きくするためのものです。
通常時は自動で最大まで大きくなりますが、親要素をflex
としたときにはflex-grow: 1;
を指定しないと幅がその子要素の大きさまで縮んでしまいます。
あとは、.btn
をposition: fixed;
とすればこの体積が0になるので、.wrapper
が丁度中央に来るように配置され、そのすぐ右隣に.btn-wrapper
が配置されます。
.btn-wrapper
には何もスタイルを設定していませんが、これは必要です。
この要素の位置を基準として、ボタンをfixed
します。
ボタンの細かな位置は、bottom
とmargin-left
で指定すれば良いでしょう。left
を使ってしまうとbtn-wrapper
の外に飛び出してしまうので注意です。
position: sticky
完成品のサンプルまとめです。
See the Pen sticky to-pagetop button by nakasu (@nakasu) on CodePen.
以下でそれぞれの場合について簡単に解説していきます。
1. ウインドウ右下にボタンを配置
ページトップボタンをウインドウ右下に固定するが、フッターとは被らないようにします。
ボタンは.content
の終わりの</div>
と<footer>
の間に挿入します。
<div class="to-pagetop"> <a href="#" class="btn">ページトップへ</a> </div>
CSSは次のように指定します。
.to-pagetop { position: sticky; bottom: 0; } .to-pagetop .btn { position: absolute; bottom: 20px; right: 20px; }
まず.to-pagetop
をコンテンツの下、フッターの上に配置します。
そしてこのto-pagetop
をbottom: 0;
(フッターの上)を基準にsticky
します。
あとはその子要素である.btn
をabsolute
で相対位置で指定します。
2. コンテンツ内の右下にボタンを配置
.wrapper
の中にボタンを入れることで、コンテンツの幅内にボタンを配置します。
ボタンは.content
の終わりの</div>
と<footer>
の間に挿入します。
<div class="to-pagetop"> <div class="wrapper"> <a href="#" class="btn">ページトップへ</a> </div> </div>
CSSは次のように指定します。
.to-pagetop { position: sticky; bottom: 0; } .to-pagetop.wrapper { position: relative; } .to-pagetop .btn{ position: absolute; bottom: 20px; right: 20px; }
まず.to-pagetop
をフッターの上にsticky
して、その中にコンテンツの幅を持つ.wrapper
を入れます。
あとは.wrapper
にposition: relative;
を指定することで、.wrapper
を基準に.btn
を配置することができます。
3. コンテンツ右下の外側にボタンを固定
コンテンツの右端の外側にボタンを固定し、フッターとは被らないようにします。
ボタンは.content
の終わりの</div>
と<footer>
の間に挿入します。
<div class="to-pagetop"> <div class="wrapper"></div> <div class="btn-wrapper"> <a href="#" class="btn">ページトップへ</a> </div> </div>
CSSは次のように指定します。
.to-pagetop { position: sticky; bottom: 0; display: flex; justify-content: center; } .to-pagetop .wrapper { margin: 0; flex-grow: 1; } .to-pagetop .btn { position: absolute; bottom: 20px; margin-left: 20px; }
まず.to-pagetop
をフッターの上にsticky
し、flex
で子要素を中央寄せします。
この.wrapper
には最初に設定したmargin
をキャンセルし、幅が最大となるようにflex-grow: 1;
を設定します。
すると.btn-wrapper
が.wrapper
の右端(=コンテンツの右端)に配置されるので、そこからの相対位置で.btn
の位置を指定します。
ただし、btn
の位置をleft
で指定すると.btn-wrapper
から飛び出してしまうので、代わりに`margin: left`を使うようにしてください。
おわりに
なんかめっちゃ長くなりました(8000字超)。
あと、これらを実装するのに丸3日ぐらい悩みました。
上の例では、正直よく理解していない挙動も使ってますが、とりあえずはちゃんと動いてるし大丈夫なのかなと思います。
まあこれぐらいはJavaScriptなしで実装しようねという話でした。
ページトップボタンだけでなく、ウインドウ右上によくあるハンバーガーメニューの配置も、上の話と同じようにして実装できるかと思います。
今日はこれくらいにしておきます。お疲れさまでした。
参考
とくになし。