設置したページ内リンクに遷移した時トップバーで隠れてしまった時の解決法

ページ内リンクに遷移したときに遷移先のテキストがトップバーの下に隠れてしまったという経験はありませんか?

これはCSSの :target 擬似クラスを使って解決することができます。

ページ内リンクとは?

「ページ内リンク」は、ページ内の特定の部分へ遷移するリンクのことです。<a> 要素の href 属性にページ内の特定の要素の ID を指定することで作成することができます。

  1. <!-- クリックするとページ内のIDが「apple」の要素へとジャンプする -->
  2. <a href="#apple">Apple</a>

「トップナビゲーションで隠れてしまう」とは?

次のブログページのデモでは、「目次」の中の項目をタップするとページ内遷移が起こります。遷移先は記事の見出しなのですが、遷移後に見出しのテキストがトップバーで隠れて見えなくなってしまいます。

これは、トップバーが position: fixed; となっていて、通常のフローから除外されていることが原因です。トップバーは常にウィンドウ最上部に固定されていますが、遷移後の見出しタグもまたウィンドウの最上部に位置します。それぞれ異なるフローにあるので重なってしまうということです。

隠れてしまわないようにする方法

ページ内遷移後の要素が固定されたトップバーに覆われてしまわないようにするには次のいずれかの対応が必要になります。

  1. トップバーを通常のフローに含める
  2. 遷移後の要素の位置をトップバーの高さ分下にずらす

先ほどのデモはトップバーを常にウィンドウ上部に固定させておきたいので、1 番目の方法は使えません。…となると、2番目の方法になりますが、CSS にはこのためにあるのではないかと思ってしまうとても便利な擬似クラスが存在します。

:target 擬似クラスを活用

:target 擬似クラスは、URL のフラグメントに一致する ID を持つ固有の要素を表します。例えば、「#apple」に遷移したら id 属性が「apple」である要素を表します。

この性質を利用して、常に対象となる要素(h1〜h6 に限らない)をセレクターにとることができるようになります。

  1. /* URL のフラグメントと一致する要素を太字にする */
  2. :target {
  3. font-weight: bold;
  4. }

トップバーの高さ分下にずらす

対象となる要素(URL のフラグメントに一致する要素)をセレクトする方法は説明しました。次にやることは、その要素をトップバーの高さ分下にずらしてテキストが隠れないよう余白を設けることです。

CSS コードは次のようになります。

  1. :target {
  2. /* トップバーの高さ以上の値を指定 */
  3. padding-top: 56px;
  4. }

ポイントは、margin-top ではなく padding-top を指定するということです。

しかし、これには問題があります。それは、ターゲット要素に余計な余白が入ってしまうことです。できれば、トップバーの高さ分下にずらしはするものの余白を入れいないというようにしたいですよね。実はそれが可能です。

ターゲット要素がトップバーに隠れないようにする
  1. :target {
  2. padding-top: 56px;
  3. margin-top: -56px;
  4. }

下にずらした分上にも同じ分ずらすのです。ネガティブマージンを使えば見た目を元に戻すことが可能となります。

【おまけ】ページ内リンクをスクロールで遷移させる(CSSで簡単実装)

ページ内リンクに遷移する際、リンクを踏むと通常は一瞬でターゲットへ遷移します。しかし、スクロールとともに遷移させることもできます。通常は jQuery などで行いますが、CSSのみで実装することができます。

scroll-behavior プロパティの値を smooth に指定することでこれが行えます。ただし、IE および Safari は未対応です。直前に紹介したデモの中ではこれが指定してありますのでスクロール遷移すると思います。

スムーズスクロール
  1. html, body {
  2. scroll-behavior: smooth;
  3. }