[CSS] テーブルのスクロール可能領域を表す影をanimation-timelineで付ける方法

5 min read

概要

テーブルのスクロール可能領域を視覚的に示すために、水平スクロール時に影を付ける手法が存在する。

これまでの方法だと、スクロール可能領域の端に影を付けるためにJavaScriptを使用してスクロール位置に応じて影の位置を調整したり、そのためにラッパー要素を用意するなどして実装が複雑になるような手法が主だった。

JavaScriptやラッパー要素を用いず、テーブル要素に対してCSSだけでスクロール可能領域を表す影を付ける実装をする。既存のHTML構造を変更せずに実現できるため、汎用性が高くなる。

実現方法

デモ

コード

:root {
  --table-shadow-color: hsla(0, 0%, 87%, 0.9);
  --table-shadow-size: 0.5rem;
  --table-shadow-spread: calc(var(--table-shadow-size) * -0.5);
}

@keyframes scroll-table-shadow-inset {
  0% {
    box-shadow:
      inset calc(var(--table-shadow-size) * -2) 0 var(--table-shadow-size) var(--table-shadow-spread)
        var(--table-shadow-color),
      inset 0 0 var(--table-shadow-size) var(--table-shadow-spread) var(--table-shadow-color);
  }
  10%,
  90% {
    box-shadow:
      inset calc(var(--table-shadow-size) * -1) 0 var(--table-shadow-size) var(--table-shadow-spread)
        var(--table-shadow-color),
      inset var(--table-shadow-size) 0 var(--table-shadow-size) var(--table-shadow-spread) var(--table-shadow-color);
  }
  100% {
    box-shadow:
      inset 0 0 var(--table-shadow-size) var(--table-shadow-spread) var(--table-shadow-color),
      inset calc(var(--table-shadow-size) * 2) 0 var(--table-shadow-size) var(--table-shadow-spread)
        var(--table-shadow-color);
  }
}

table {
  display: block; /* テーブルの内側をスクロール用 */
  overflow-x: auto; /* テーブルの内側をスクロール用 */
  max-width: 100%; /* テーブルの内側をスクロール用 */
  animation: scroll-table-shadow-inset linear; /* 影のアニメーション */
  animation-timeline: scroll(self x); /* スクロール連動 */
}

解説

先述のコードを解説する。

テーブルの内側をスクロールする

table {
  display: block;
  overflow-x: auto;
  max-width: 100%;
}
  1. display: block;
    • widthheightプロパティが効くようになり、オーバーフローやスクロールの制御が可能になる
  2. overflow-x: auto;
    • 指定された横幅を超える場合、スクロールバーが有効になる
    • 内容が収まる場合、スクロールバーは表示されない

さらにth,td要素にwhite-space: nowrap;を指定して、テキストが折り返されないようにしておくと良い。

@keyframes scroll-table-shadow-inset

@keyframes scroll-table-shadow-inset {
  0% {
    /* 左側に濃い影、右側に薄い影 */
    box-shadow:
      inset calc(var(--table-shadow-size) * -2) 0 var(--table-shadow-size) var(--table-shadow-spread)
        var(--table-shadow-color),
      inset 0 0 var(--table-shadow-size) var(--table-shadow-spread) var(--table-shadow-color);
  }
  10%,
  90% {
    /* 左右両側に均等な影 */
    box-shadow:
      inset calc(var(--table-shadow-size) * -1) 0 var(--table-shadow-size) var(--table-shadow-spread)
        var(--table-shadow-color),
      inset var(--table-shadow-size) 0 var(--table-shadow-size) var(--table-shadow-spread) var(--table-shadow-color);
  }
  100% {
    /* 右側に濃い影、左側に薄い影 */
    box-shadow:
      inset 0 0 var(--table-shadow-size) var(--table-shadow-spread) var(--table-shadow-color),
      inset calc(var(--table-shadow-size) * 2) 0 var(--table-shadow-size) var(--table-shadow-spread)
        var(--table-shadow-color);
  }
}
  1. アニメーションの定義:
    @keyframes scroll-table-shadow-insetで、スクロールに応じて変化する影の状態を定義する
    • 影はbox-shadowを使用してテーブルの内側(inset)に表現する
      • 0%(開始時): 左側に濃い影、右側に薄い影
      • 10%〜90%(中間): 左右両側に均等な影
      • 100%(終了時): 右側に濃い影、左側に薄い影
  2. アニメーションの適用:
    テーブル要素にanimation: scroll-table-shadow-inset linear;animation-timeline: scroll(self x);を指定することで、水平スクロールに連動してアニメーションする
  3. スクロール連動:
    animation-timeline: scroll(self x);は、要素自体の水平スクロール位置に基づいてアニメーションを制御する
    これにより、スクロール位置に応じて影の位置が変化し、スクロール可能領域を視覚的に示すことができる

注意点

執筆当時、animation-timelineが一部のブラウザでしかサポートされていない。

ChromeEdgeFirefoxSafari
✅ 115✅ 1151

https://caniuse.com/mdn-css_properties_animation-timeline

参考

注釈

  1. Firefox はlayout.css.scroll-driven-animations.enabledフラグをtrueにすることでバージョン110から有効になる。