KINTO Tech Blog
Development

HTMLのアンカータグ(aタグ)でページの特定部分までスクロールしたら微調整が必要かもという話

Cover Image for HTMLのアンカータグ(aタグ)でページの特定部分までスクロールしたら微調整が必要かもという話

はじめに

こんにちは。KINTO Technologiesのグローバル開発部でフロントエンド開発をしているクリスです。

今日はフロントエンドの開発におけるちょっとした詰まったこととそれの解決策について紹介したいと思います!

詰まったこと

普段みなさんは以下のようにアンカータグ(aタグ)を使ってとあるページの特定部分までスクロールさせたい時ありますよね?
スクロール先の要素にidを付与し、aタグにhref="#{id}"をつければそれが実現できます。

<a href="#section-1">Section 1</a>
<a href="#section-2">Section 2</a>
<a href="#section-3">Section 3</a>
<section class="section" id="section-1">
  Section 1
</section>
<section class="section" id="section-2">
  Section 2
</section>
<section class="section" id="section-3">
  Section 3
</section>

no-header

記事や規約など長いページだと、ユーザーにとって役に立ちます。

しかし、現実では多くの場合、ヘッダーといったページの上に固定する要素があって、aリンクをクリックし、スクロールされた後に少し位置がずれてしまいます。

例えば以下のようなヘッダーがあるとします。

<style>
  header {
    position: fixed;
    top: 0;
    width: 100%;
    height: 80px;
    background-color: #989898;
    opacity: 0.8;
  }
</style>
<header style="">
  <a href="#section-1">......</a>
  <a href="#section-2">......</a>
  <a href="#section-3">......</a>
  ...
</header>

あえてこのヘッダーを少し透過にしましたが、aリンクをクリックして、移動になった後に、一部のコンテンツがヘッダーの後ろに隠れてしまったことがわかります。

with-header

HTMLとCSSだけを用いた解決策

aリンクをクリックした時に、Javascriptでヘッダーの高さを取得し、スクロール位置からヘッダーの高さを引いてスクロールさせれば問題解決できますが、今日はHTMLとCSSを用いた解決策を紹介したいと思います。具体的には本来到達したい<section>より少し上に別の<div>を用意し、その要素までスクロールさせる方法です。

先ほどの例に戻って、まず各セッションの中に一つのdivタグを作ります。そして該当divタグに一つのclass、例えばanchor-offsetを付与し、さらに元々<section>タグに付与したidも新しく作ったdivタグに移します。

<section>
  <div class="anchor-offset" id="section-1"></div>
  <h1>Section 1</h1>
  ...
</section>

そしてcssで<section>タグと.anchor-offsetのスタイル定義をします。

/* アンカーを設置する必要がある要素のみ付与したい場合はclassを利用 */
section {
  position: relative;
}

.anchor-offset {
  position: absolute;
  height: 80px;
  top: -80px;
  visibility: hidden;
}

上記のように設定すると、aリンクをクリックした時に、該当する<section>の本位置ではなく、それより少し(例の場合では80px)上の部分までスクロールされ、ヘッダーの高さ(80px)と相殺されます。

anchor-offset

Vueにおける書き方

Vueでは値をcssにバインドすることができます。この機能を利用し、高さを動的に設定しコンポーネントにすれば、さらにメインテナンスしやすくなると思います。

<template>
  <div :id="props.target" class="anchor-offset"></div>
</template>

<script setup>
const props = defineProps({
  target: String,
  offset: Number,
})
const height = computed(() => {
  return `${props.offset}px`
})
const top = computed(() => {
  return `-${props.offset}px`
})
</script>

<style scoped lang="scss">
.anchor-offset {
  position: absolute;
  height: v-bind('height');
  top: v-bind('top');
  visibility: hidden;
}
</style>

まとめ

以上、aタグでページの特定部分までスクロールする際にヘッダーなどの固定要素に合わせたスクロール位置の調整方法でした。
他にも色々なやり方がありますが、ご参考になれたらと思います!

Facebook

関連記事 | Related Posts

We are hiring!

【フロントエンドエンジニア(コンテンツ開発)】新車サブスク開発G/東京

新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。​業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、クルマのサブスクリプションサービス『KINTO ONE』のWebサイトコンテンツの開発・運用業務を担っていただきます。

WEBエンジニア /システム開発G /東京

システム開発Gについて各国のKINTOビジネスの成長を支援すべく、そのシステムプラットフォームの全体デザイン、設計、開発、導入を担うグループとなります。新しいグローバルプロダクト・プロジェクトに関わり、ゼロイチに関わる機会が存分にあります。