scroll-stateによりCSSのみでトップに戻るボタンの表示・非表示が実装可能になった

scroll-stateとは

scroll-stateはCSSのコンテナクエリの一部として導入された機能で、特定のスクロール状態に基づいてスタイルを適用できます。

scroll-stateを使用するとスクロールの進行状況に応じた動的なスタイルを適用できます。

Chrome v133以上で使用可能なので、Chrome v132以下の場合はChromeをアップデートするか、Chrome ベータ版を使用してください。

scroll-stateを使用した表示・非表示

scroll-stateを使用することにより、CSSのみでトップに戻るボタンの表示・非表示が実装可能になりました。

今までは「トップに戻る」のスムーススクロールは「scroll-behavior: smooth」で実装できましたが、画面右下に表示させる「トップに戻る」ボタン自体の表示・非表示はJavaScriptでなければ実装できませんでした。

しかし、scroll-stateならCSSだけで画面の一番下までスクロールした際に「トップに戻る」ボタンを表示させる処理を実装できます。

やり方は、まずhtmlに「overflow: hidden」、bodyに「container-type: scroll-state」などのプロパティを以下のように追加します。

CSS
html {
  overflow: hidden;
}

body {
  height: 100vh;
  container-type: scroll-state;
  overflow: auto;
  scroll-behavior: smooth;
}

さらにトップに戻るボタン(#backToTop)に表示時のスタイルを適用して、一番下までスクロールした際のスタイルを@container scroll-state(scrollable: bottom) 内に記述すれば完成です。

JavaScriptを使用しないトップに戻るボタンが実装できました。

CSS
#backToTop {
  transform: translateY(0);
  transition: transform 0.5s;
  position: fixed;
  bottom: 20px;
  right: 20px;
  padding: 10px 20px;
  background: #333;
  color: #fff;
  text-decoration: none;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  opacity: 1;
}

@container scroll-state(scrollable: bottom) {
  #backToTop {
    transform: translateY(100px);
    opacity: 0;
  }
}

HTMLは以下のようになっています。

HTML
<div id="top"></div>
<h1>CSSのみで実装したBack to Topのサンプル</h1>
<p>一番下までスクロールしてください。</p>
<p>一番下までスクロールしてください。</p>
<p>一番下までスクロールしてください。</p>
<p>一番下までスクロールしてください。</p>
<p>一番下までスクロールしてください。</p>
<p>一番下までスクロールしてください。</p>
<footer id="footer">footer</footer>
<a href="#top" id="backToTop">Back To Top</a>
scroll-stateによりCSSのみでトップに戻るボタンの表示・非表示が実装可能になった

CSSのみで実装したBack to Topのサンプル

CSSのみで実装すると、アンカーがURLに付いてしまう

CSSのみのトップに戻るボタンの実装だと、アンカーリンクとscroll-behavior: smoothを使用してスムーススクロールを発生しているため、URLにアンカー(例: #top)が付いてしまいます。

これが付くとブラウザのURLに#topが付いて、URLの見栄えが悪くなるため、技術的にはCSSだけでもスムーススクロールが可能になりましたが、JavaScriptで実装しているケースが多いです。

scroll-behavior: smoothを使わない場合は以下のJavaScriptのコードが必要になります。

JavaScript
// <button id="backToTop">Back to Top</button>
const backToTop = document.getElementById('backToTop')

backToTop.addEventListener('click', () => {
    document.body.scrollTo({ top: 0, behavior: 'smooth' })
})

CSSのみで実装したBack to Top (scroll-behaviorなし)のサンプル

特定の要素が見えたときに表示できない

scroll-stateを使用すれば一番下までスクロールした際にトップに戻るボタンを表示させることはできますが、例えばフッターの要素が画面内に表示された際にトップに戻るボタンを表示させることはできません。

フッターに高さがある場合は一番下までスクロールしてからではなく、UI/UXの観点からフッターの要素が見えてからボタンを表示させたほうが良いです。

JavaScript
const backToTop = document.getElementById('backToTop')

const observerOptions = {
  root: null,
  rootMargin: '0px',
  threshold: 0,
}

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      backToTop.classList.add('visible')
    } else {
      backToTop.classList.remove('visible')
    }
  })
}, observerOptions)

observer.observe(footer)

CSSのみで実装しないBack to Topのサンプル

まとめ

CSSのscroll-behaviorとscroll-stateを使用すると、完全にCSSのみでトップに戻るボタンの表示・非表示を実装することが可能です。

しかし、技術的には可能になりましたが「アンカーがURLに付いてしまう」、「特定の要素が見えたときに表示できない」などのデメリットがあるため、実際にCSSのみで実装するケースは限られます。

コードもJavaScriptのscrollToとIntersectionObserverを使用したほうがシンプルになりますし、拡張性が高いので、スムーススクロールとトップに戻るボタンの表示・非表示をCSSのみで実装するのはオススメしません。