【完全保存版】CSSだけで作る横スクロールアニメーション大全|無限ループ・パララックス・レスポンシブ対応まで徹底解説

css-horizontal-scroll-animation css
記事内に広告が含まれています。

Webサイトに動きを加えたいとき、真っ先に思い浮かぶのが「アニメーション」ですが、最近注目されているのが“横スクロールアニメーション”です。画像やテキストが横に流れる演出は、視覚的にインパクトがあり、ギャラリーやスライダー、LP(ランディングページ)などで活躍します。ただし、「JavaScriptは使いたくない」「CSSだけで実装できるの?」「レスポンシブ対応は難しそう」など、疑問や不安を感じる方も多いのではないでしょうか。

本記事では、CSSだけで横スクロールアニメーションを実現する方法を、基本から応用までわかりやすく解説します。コピペで使えるサンプルコードはもちろん、スマホ対応やSEO・パフォーマンス対策までしっかりカバーしているので、初心者の方から実務で活用したい方まで幅広く役立つ内容です。

この記事を読んでわかること

  • scroll-snap-typeやoverflow-xを使ったスムーズな横スクロールの仕組み
  • @keyframesとtransformで要素を横に動かすアニメーションの作り方
  • HTML+CSSのみで完結する横スクロールのコピペ可能な実装例
  • 無限ループ、ユーザー操作、パララックス風など目的別の応用テクニック
  • スマホでも快適に動くレスポンシブ設計のコツ
  • SEOとパフォーマンスに優れたアニメーション実装のポイント
  • アクセシビリティを意識した横スクロールUIの作り方

CSSだけでどこまでできるのか?その可能性を広げたい方は、ぜひ最後までチェックしてみてください。

CSSで作る横スクロールアニメーションの基本構造

Webサイトに動きとインタラクションを加える「CSS横スクロールアニメーション」は、ユーザーエクスペリエンスを向上させる強力なツールです。JavaScriptやjQueryといったスクリプト言語を使わずに、CSSのみで実装できるため、パフォーマンスの懸念も少なく、実装も比較的容易です。このセクションでは、CSSだけで横スクロールアニメーションを実現するための最も基本的な構造と、そのために必要なプロパティについて深く掘り下げていきます。HTMLの記述例と、それに対応するCSSコードをセットで提供し、それぞれのプロパティがどのように機能するのかを明確に解説することで、初心者の方でも安心して実装に取り組めるようサポートします。

scroll-snap-typeとoverflow-xでスムーズなスクロールを実現

横スクロールコンテンツを実装する上で、まず基本となるのがoverflow-xプロパティです。これは、要素のコンテンツがX軸方向にはみ出した場合に、どのように表示するかを制御します。

overflow-x: scroll;の役割と具体的な記述方法

overflow-x: scroll;を設定することで、要素のコンテンツが親要素の幅を超えた際に、横方向のスクロールバーが表示され、ユーザーが手動でスクロールできるようになります。これにより、限られたスペース内に多くの情報を効率的に表示することが可能になります。

<div class="scroll-container">
  <div class="scroll-item">コンテンツ 1</div>
  <div class="scroll-item">コンテンツ 2</div>
  <div class="scroll-item">コンテンツ 3</div>
  <div class="scroll-item">コンテンツ 4</div>
</div>
.scroll-container {
  width: 100%;
  overflow-x: scroll; /* 横スクロールを可能にする */
  white-space: nowrap; /* 子要素を折り返さない */
}

.scroll-item {
  display: inline-block; /* 横並びにする */
  width: 80%; /* 各アイテムの幅 */
  height: 200px;
  margin-right: 20px;
  background-color: #e0e0e0;
  line-height: 200px;
  text-align: center;
  font-size: 1.5em;
  white-space: normal; /* 各アイテム内のテキストは折り返す */
}

このコードでは、scroll-containeroverflow-x: scroll;を設定することで、その中のscroll-itemが横一列に並び、コンテナの幅を超えた場合に横スクロールが可能になります。white-space: nowrap;は子要素が改行されないようにするために重要です。

scroll-snap-typex mandatory / x proximity)の概念、設定方法、使用例

scroll-snap-typeは、スクロールの停止位置を制御し、ユーザーがスクロールを終えたときに、コンテンツが特定の場所(スナップポイント)に「カチッ」と吸い付くように配置される機能です。これにより、画像ギャラリーやカルーセルなどで、各コンテンツが画面の中心や端にきれいに収まる、非常にユーザーフレンドリーなUIを実現できます。

  • x mandatory: スナップポイントに必ず吸着します。スクロールの中途半端な位置で止まることがなく、常にコンテンツの始まりや終わりに揃えたい場合に最適です。
  • x proximity: スナップポイントの近くでスクロールを止めた場合に吸着します。完全に吸着させる必要はなく、より自由なスクロール体験を提供したい場合に適しています。
.scroll-container {
  /* ... (上記のoverflow-xなど) ... */
  scroll-snap-type: x mandatory; /* 横方向への強制的なスナップ */
  -webkit-overflow-scrolling: touch; /* iOSでのスクロールを滑らかにする */
}

.scroll-item {
  /* ... (上記のdisplay: inline-blockなど) ... */
  scroll-snap-align: center; /* 各アイテムを中央にスナップ */
}

上記のCSSでは、scroll-containerscroll-snap-type: x mandatory;を設定し、scroll-itemscroll-snap-align: center;を設定しています。これにより、ユーザーがスクロールを停止すると、各scroll-itemがコンテナの中央に「カチッ」と吸い付くように停止します。

scroll-snap-type - CSS: カスケーディングスタイルシート | MDN
scroll-snap-type は CSS のプロパティで、スクロールコンテナーに設定され、スナップポート内のスナップポイントの強制の方向と厳格さを設定することで、スクロールスナップを有効にします。

scroll-snap-alignscroll-paddingなど関連プロパティも併せて解説

  • scroll-snap-align: スナップポイントとなる要素が、スクロールコンテナ内のどこに揃えられるかを指定します。start(先頭)、end(末尾)、center(中央)があります。
  • scroll-padding: スナップポイントの基準位置に内側の余白を設定します。例えば、ヘッダーが固定されている場合に、その下にスナップポイントが隠れないように調整できます。scroll-padding-top, scroll-padding-right, scroll-padding-bottom, scroll-padding-left、一括指定のscroll-paddingがあります。

これらのプロパティを組み合わせることで、ユーザーが快適に操作できる、洗練された横スクロールUIを構築できます。

scroll-snap-align - CSS: カスケーディングスタイルシート | MDN
scroll-snap-align プロパティは、ボックスのスナップ位置を、そのスナップコンテナーのスナップポート(つまり配置コンテナー)の中におけるスナップ領域(つまり 配置対象物)の配置として指定します。
scroll-padding - CSS: カスケーディングスタイルシート | MDN
scroll-padding は一括指定プロパティで、要素のすべての辺に一度にスクロールパディングを設定します。 padding プロパティで要素のパディングを設定するのとよく似ています。

@keyframesとtransform: translateX()で要素を動かす具体例

次に、CSSアニメーションの核となる@keyframesルールと、要素の移動に広く使われるtransform: translateX()について解説します。これらを組み合わせることで、要素を自動的に横方向に動かすアニメーションを作成できます。

CSSアニメーションの基本である@keyframesの定義方法

@keyframesルールは、アニメーションの各段階(フレーム)での要素のスタイルを定義します。アニメーションの開始時、中間、終了時など、任意の時点で要素がどのような状態になるかを指定できます。

構文は以下の通りです。

@keyframes アニメーション名 {
  from {
    /* アニメーション開始時のスタイル */
  }
  to {
    /* アニメーション終了時のスタイル */
  }
}

または、パーセンテージで詳細な段階を指定することも可能です。

@keyframes アニメーション名 {
  0% {
    /* アニメーション開始時のスタイル */
  }
  50% {
    /* アニメーション中間のスタイル */
  }
  100% {
    /* アニメーション終了時のスタイル */
  }
}

transform: translateX()を使った要素の横移動の仕組み

transformプロパティは、要素の形状、位置、サイズ、回転などを変更するために使用されます。その中でもtranslateX()は、要素をX軸(横方向)に移動させる関数です。

translateX(値): 要素を横方向に移動させます。

  • 正の値(例: 100px, 50%)を指定すると、要素は右へ移動します。
  • 負の値(例: 100px, 50%)を指定すると、要素は左へ移動します。

このtransform: translateX()@keyframes内で使用することで、要素をスムーズに横移動させるアニメーションを定義できます。

animationプロパティの各値と簡単な四角い要素が左右に動くアニメーションのHTMLとCSSコード例

animationプロパティは、@keyframesで定義したアニメーションを要素に適用するためのショートハンドプロパティです。複数のサブプロパティを一括で指定できます。

主なサブプロパティ:

  • animation-name: 適用する@keyframesのアニメーション名。
  • animation-duration: アニメーションの完了にかかる時間(例: 2s, 500ms)。
  • animation-timing-function: アニメーションの速度曲線(例: ease, linear, ease-in-out)。
  • animation-iteration-count: アニメーションの繰り返し回数(infiniteで無限ループ)。
  • animation-direction: アニメーションの再生方向(normal, reverse, alternate, alternate-reverse)。
  • animation-fill-mode: アニメーションが開始前、または終了後に要素にスタイルを適用するかどうか(forwards, backwards, both, none)。

簡単な四角い要素が左右に動くアニメーションの例:

<div class="moving-box"></div>
.moving-box {
  width: 100px;
  height: 100px;
  background-color: dodgerblue;
  position: relative; /* animation-nameを適用するために必要 */
  animation: slideBox 3s ease-in-out infinite alternate;
}

@keyframes slideBox {
  0% {
    transform: translateX(0); /* 開始位置 */
  }
  100% {
    transform: translateX(200px); /* 終了位置 */
  }
}

このコードでは、.moving-boxslideBoxというアニメーションを3秒かけて無限に繰り返します。alternateが指定されているため、アニメーションは右に移動した後、左に戻る動きを繰り返します。

実際の表示

See the Pen css-horizontal-scroll-animation-01 by watashi-xyz (@watashi-xyz) on CodePen.

コピペOK!HTML+CSSのシンプルな横スクロール実装サンプル

これまでに学んだプロパティを組み合わせ、実際にすぐに使える横スクロールアニメーションのサンプルコードを紹介します。ここでは、「3枚の画像が横に並び、手動でスムーズにスクロールできるカルーセル風UI」と「シンプルなテキストが左右に無限ループするティッカー」の2つの例を提供します。

例1:スクロールスナップを活用した画像カルーセル

ユーザーが手動でスクロールすると、各画像がきれいに中央にスナップするカルーセルです。

<div class="image-carousel">
  <img src="https://placehold.jp/400x200.png?text=Image1" alt="画像1" class="carousel-item">
  <img src="https://placehold.jp/400x200.png?text=Image2" alt="画像2" class="carousel-item">
  <img src="https://placehold.jp/400x200.png?text=Image3" alt="画像3" class="carousel-item">
  <img src="https://placehold.jp/400x200.png?text=Image4" alt="画像4" class="carousel-item">
</div>
.image-carousel {
  width: 100%;
  max-width: 800px; /* 最大幅を指定 */
  margin: 0 auto;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch; /* iOSでのスクロールを滑らかにする */
  display: flex; /* 子要素を横並びにする */
  gap: 20px; /* アイテム間の余白 */
  padding-bottom: 20px; /* スクロールバーとの重なりを防ぐ */
}

.carousel-item {
  flex: 0 0 auto; /* アイテムの縮小・拡大を禁止し、幅はコンテンツに合わせる */
  width: 90%; /* ビューポート幅に対するアイテムの表示幅 */
  max-width: 400px; /* 各画像の最大幅 */
  height: auto;
  scroll-snap-align: center; /* 各アイテムを中央にスナップ */
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* スクロールバーのスタイルをカスタマイズ(任意) */
.image-carousel::-webkit-scrollbar {
  height: 8px;
}

.image-carousel::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.image-carousel::-webkit-scrollbar-thumb {
  background: #888;
  border-radius: 4px;
}

.image-carousel::-webkit-scrollbar-thumb:hover {
  background: #555;
}

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

例2:シンプルなテキストの無限ループティッカー

ニューステロップやロゴスライダーによく見られる、テキストが自動で横に流れ続ける無限ループアニメーションです。

<div class="ticker-container">
  <div class="ticker-content">
    <span>これは流れるテキストのサンプルです。</span>
    <span>Web制作に役立つ情報をお届けします!</span>
    <span>CSSアニメーションの可能性を探ろう!</span>
    <span>無限ループはこれで完璧。</span>
  </div>
</div>
.ticker-container {
  width: 100%;
  overflow: hidden; /* コンテナからはみ出た部分を非表示 */
  white-space: nowrap; /* テキストを折り返さない */
  box-sizing: border-box;
  background-color: #f0f0f0;
  padding: 10px 0;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
}

.ticker-content {
  display: inline-block;
  animation: moveTicker 20s linear infinite; /* アニメーション適用 */
  padding-right: 100%; /* コンテンツが途切れないように余白を追加 */
}

.ticker-content span {
  display: inline-block;
  padding: 0 30px; /* 各テキスト間の余白 */
  font-size: 1.2em;
  color: #333;
}

@keyframes moveTicker {
  0% {
    transform: translateX(0%);
  }
  100% {
    transform: translateX(-100%); /* 左に100%移動 */
  }
}

このティッカーでは、.ticker-contentの幅がticker-containerの幅を超えるように設定し、translateX(-100%)で左に移動させることで無限ループを実現しています。コンテンツが途切れないように、padding-right: 100%;で十分な余白を確保しています。

実際の表示

See the Pen css-horizontal-scroll-animation-03 by watashi-xyz (@watashi-xyz) on CodePen.

【目的別】CSS横スクロールアニメーションの応用テクニック集

CSS横スクロールアニメーションの基本的な構造を理解したところで、次はより実践的で多様な表現方法を学ぶことで、Webサイトの表現力を格段に向上させましょう。このセクションでは、自動ループするギャラリー、ユーザー操作に反応するスライダー、そして縦スクロールと連動するパララックス風演出といった、目的別の応用テクニックを解説します。それぞれのテクニックについて、具体的なHTML構造とCSSコード例を示し、カスタマイズのポイントを明確にすることで、あなたのアイデアを形にする手助けをします。

無限ループする自動横スクロールギャラリーの作り方(画像・テキスト対応)

Webサイトでよく見かける、ロゴや画像を自動で横スクロールさせる「無限ループギャラリー」は、サイトに活気と動的な印象を与える効果があります。CSSだけでこれを実現するには、コンテンツを複製し、@keyframestransform: translateX()を使って連続的に移動させるのが一般的な方法です。

コンテンツを複製してシームレスなループを実現するテクニック

途切れることなく滑らかなループアニメーションを実現するためには、オリジナルのコンテンツの直後に同じコンテンツを複製して配置するのがポイントです。アニメーションがコンテンツの終わりまで到達すると、複製されたコンテンツの始まりにシームレスにつながるように、translateX()の移動量を調整します。

<div class="loop-gallery-container">
  <div class="loop-gallery-track">
    <img src="https://placehold.jp/150x50.png?text=Logo1" alt="ロゴ1" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo2" alt="ロゴ2" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo3" alt="ロゴ3" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo4" alt="ロゴ4" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo5" alt="ロゴ5" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo1" alt="ロゴ1" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo2" alt="ロゴ2" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo3" alt="ロゴ3" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo4" alt="ロゴ4" class="loop-item">
    <img src="https://placehold.jp/150x50.png?text=Logo5" alt="ロゴ5" class="loop-item">
  </div>
</div>
.loop-gallery-container {
  width: 100%;
  overflow: hidden; /* コンテナからはみ出た部分を非表示 */
  white-space: nowrap; /* 子要素を折り返さない */
  margin: 40px 0;
  background-color: #f9f9f9;
  padding: 20px 0;
}

.loop-gallery-track {
  display: inline-block; /* 横並びにする */
  animation: scrollLoop 20s linear infinite; /* アニメーション適用 */
}

.loop-item {
  display: inline-block;
  width: 150px; /* アイテムの幅 */
  height: 100px;
  margin: 0 10px; /* アイテム間の余白 */
  vertical-align: middle; /* 縦方向の位置調整 */
}

@keyframes scrollLoop {
  0% {
    transform: translateX(0);
  }
  100% {
    /* 複製されたコンテンツの幅分、左に移動 */
    /* ここでの -50% は、track内のコンテンツを複製した際に合計が200%になることを想定 */
    /* 各アイテムの合計幅に基づいて正確なpx値やvw値を使用するのがより安全 */
    transform: translateX(-50%); 
  }
}

/* ホバーでアニメーション一時停止(オプション) */
.loop-gallery-container:hover .loop-gallery-track {
  animation-play-state: paused;
}

@keyframes scrollLoop100%transform: translateX()の値は、複製されたコンテンツの合計幅に合わせて調整する必要があります。上記コードの-50%は、loop-gallery-track内にオリジナルコンテンツと全く同じ幅の複製コンテンツが続く場合、全体の50%(つまりオリジナルコンテンツ部分の幅)だけ移動すればシームレスにループするという意味合いです。

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

animation-delayanimation-direction (alternate) を活用したバリエーション

  • animation-delay: アニメーションの開始を遅らせる時間。複数の要素をずらして動かしたい場合に便利です。
  • animation-direction: alternate;: アニメーションを順方向と逆方向で交互に再生します。行ったり来たりするような動きを実現できます。
/* alternate を使った例 */
.loop-gallery-track.alternate {
  animation: scrollLoopAlternate 20s ease-in-out infinite alternate;
}

@keyframes scrollLoopAlternate {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-50%); /* ある程度移動 */
  }
}

ユーザー操作(ホバー・クリック)に反応するインタラクティブな横スライダー

CSSのみでユーザーの操作に反応するインタラクティブなスライダーを構築するには、主に擬似クラスや特定のHTML構造を工夫する「CSSハック」が利用されます。JavaScriptを使わずに、ユーザーが矢印をクリックしたり、要素にマウスを乗せたりすることで、スライダーが動くように見せることができます。

CSSの:hover:focus疑似クラス、またはJavaScriptなしで実現できるテクニック

  • :hover: 要素にマウスが乗ったときにスタイルを適用します。これをアニメーションの一時停止や、関連要素の表示・非表示に利用できます。
  • チェックボックスハック: input type="checkbox"label要素を組み合わせて、JavaScriptなしでクリック操作による要素の表示・非表示、またはスライダーの切り替えを実現する手法です。checked擬似クラスが利用されます。

チェックボックスハックを使った横スライダーの例:

この例では、ラジオボタン(input type="radio")を使って、対応するコンテンツを表示するシンプルなスライダーを実装します。

<div class="interactive-slider-container">
  <input type="radio" name="slider" id="slide1" checked class="slider-radio">
  <input type="radio" name="slider" id="slide2" class="slider-radio">
  <input type="radio" name="slider" id="slide3" class="slider-radio">

  <div class="slider-controls">
    <label for="slide1" class="slider-dot"></label>
    <label for="slide2" class="slider-dot"></label>
    <label for="slide3" class="slider-dot"></label>
  </div>

  <div class="slider-content-wrapper">
    <div class="slider-content">
      <div class="slider-panel">パネル 1</div>
      <div class="slider-panel">パネル 2</div>
      <div class="slider-panel">パネル 3</div>
    </div>
  </div>
</div>
.interactive-slider-container {
  width: 100%;
  max-width: 600px;
  margin: 40px auto;
  overflow: hidden;
  position: relative;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.slider-radio {
  display: none; /* ラジオボタンを非表示 */
}

.slider-content-wrapper {
  overflow: hidden;
}

.slider-content {
  display: flex;
  width: 300%; /* パネル数 x 100% */
  transition: transform 0.5s ease-in-out; /* スライドのアニメーション */
}

.slider-panel {
  flex: 0 0 calc(100% / 3); /* パネル数に応じて幅を調整 */
  height: 250px;
  background-color: #f0f8ff;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2em;
  color: #333;
}

/* ラジオボタンがチェックされた時にコンテンツをスライド */
#slide1:checked ~ .slider-content-wrapper .slider-content {
  transform: translateX(0%);
}
#slide2:checked ~ .slider-content-wrapper .slider-content {
  transform: translateX(-33.333%); /* 100% / パネル数 */
}
#slide3:checked ~ .slider-content-wrapper .slider-content {
  transform: translateX(-66.666%); /* 200% / パネル数 */
}

.slider-controls {
  text-align: center;
  margin-top: 15px;
}

.slider-dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  background-color: #bbb;
  border-radius: 50%;
  margin: 0 5px;
  cursor: pointer;
  transition: background-color 0.3s;
}

/* 選択されたドットのスタイル */
#slide1:checked ~ .slider-controls .slider-dot:nth-child(1),
#slide2:checked ~ .slider-controls .slider-dot:nth-child(2),
#slide3:checked ~ .slider-controls .slider-dot:nth-child(3) {
  background-color: dodgerblue;
}

このコードでは、非表示のラジオボタンの状態をCSSセレクタで監視し、それに応じて.slider-contenttranslateXで移動させています。ドットナビゲーションはlabel要素でラジオボタンと紐付けられています。

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

縦スクロールと連動!パララックス風横スクロール演出の実装

縦方向のスクロール量に応じて、特定の要素が横方向にアニメーションする「パララックス風」の演出は、Webサイトに奥行きとダイナミックな印象を与えます。これは、position: sticky;transform: translateX()の組み合わせや、比較的新しいCSS機能であるanimation-timelineを使用することで実現できます。

position: sticky;transform: translateX()の組み合わせ

この方法は、特定の要素をスクロール領域内で「固定」しつつ、その要素が固定されている間(または指定された範囲内をスクロールしている間)に横方向へ移動させるものです。

<div class="scroll-section">
  <div class="sticky-wrapper">
    <div class="parallax-horizontal-content">
      <div class="parallax-item">アイテム A</div>
      <div class="parallax-item">アイテム B</div>
      <div class="parallax-item">アイテム C</div>
      <div class="parallax-item">アイテム D</div>
    </div>
  </div>
</div>

<div class="dummy-space"></div> ```

```css
.scroll-section {
  height: 150vh; /* このセクションをスクロールする長さ */
  position: relative;
  background-color: #fff;
  overflow: hidden; /* コンテンツがはみ出さないように */
}

.sticky-wrapper {
  position: sticky;
  top: 0;
  height: 100vh; /* スクロール領域の高さ */
  overflow: hidden;
  display: flex;
  align-items: center;
}

.parallax-horizontal-content {
  display: flex;
  width: 400%; /* アイテム数 * 100% を超える幅 */
  position: absolute;
  left: 0; /* 左端から開始 */
  /* スクロール量に合わせてJavaScriptでtranslateXを制御する想定 */
  /* CSSのみで実現する場合、animation-timelineを使用 */
}

.parallax-item {
  flex: 0 0 100vw; /* ビューポート幅に合わせてアイテム幅を設定 */
  height: 80vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 3em;
  color: #fff;
  background-color: #3f51b5; /* 色は適宜変更 */
  border-right: 1px solid rgba(255, 255, 255, 0.3);
}

.parallax-item:nth-child(even) {
  background-color: #ff9800;
}

.dummy-space {
  height: 100vh; /* 最後のセクションをスクロールするためのスペース */
  background-color: #eee;
}

/* JavaScriptでtranslateXを制御する場合の概念 */
/* window.addEventListener('scroll', () => {
  const scrollY = window.scrollY;
  const sectionTop = document.querySelector('.scroll-section').offsetTop;
  const sectionHeight = document.querySelector('.scroll-section').offsetHeight;
  const scrollProgress = Math.min(1, Math.max(0, (scrollY - sectionTop) / (sectionHeight - window.innerHeight)));

  // translateXの値をスクロール進捗に合わせて計算
  // 例: コンテンツの総幅 - 100vw
  const moveAmount = (document.querySelector('.parallax-horizontal-content').scrollWidth - window.innerWidth) * scrollProgress;
  document.querySelector('.parallax-horizontal-content').style.transform = `translateX(-${moveAmount}px)`;
}); */

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

このCSSのみでは、parallax-horizontal-contenttranslateXは自動で動きません。縦スクロール量と連動させるには、通常JavaScriptでのスクロールイベントリスナーを組み合わせる必要があります。しかし、近年、CSSだけでスクロール連動アニメーションを実現するanimation-timelineというプロパティが登場しました。

animation-timelineを活用したスクロール連動型アニメーションのCSS実装例

animation-timelineは、CSSアニメーションのタイムラインを、通常の時間ベースではなく、スクロール位置や要素の可視性(ビューポートへの入り込み具合)に紐付けることができる非常に強力な機能です。これにより、JavaScriptを使わずにパララックス効果などを実装できるようになります。

注意点: animation-timelineと関連プロパティ(view-timelinescroll-timeline)は比較的新しいCSS機能であり、まだ全てのブラウザで完全にサポートされているわけではありません(特にSafariでのサポートが限定的です)。利用する際は、ブラウザの互換性(Can I use?などで確認)とフォールバックの検討が必要です。

animation-timelineを使った例(概念的な実装):

<div class="scroll-section">
  <div class="sticky-wrapper">
    <div class="parallax-horizontal-content">
      <div class="parallax-item">アイテム A</div>
      <div class="parallax-item">アイテム B</div>
      <div class="parallax-item">アイテム C</div>
      <div class="parallax-item">アイテム D</div>
    </div>
  </div>
</div>

<div class="dummy-space"></div>
.parallax-horizontal-content {
  display: flex;
  width: 400%; /* アイテム数 * 100% を超える幅 */
  animation: scroll-horizontal linear forwards; /* アニメーション定義 */
  animation-timeline: scroll(self x); /* この要素の横スクロールにタイムラインを紐付け */
  /* または、縦スクロールに紐付ける場合 */
  /* animation-timeline: scroll(root); */
}

@keyframes scroll-horizontal {
  from {
    transform: translateX(0);
  }
  to {
    /* コンテンツの総幅からビューポート幅を引いた分だけ左に移動 */
    transform: translateX(calc(-100vw * 3)); /* 例: 4アイテムで3つ分移動 */
  }
}

/* rootの縦スクロールに紐付ける場合 */
/* body {
  scroll-timeline-name: --page-scroll;
  scroll-timeline-axis: block;
}

.parallax-horizontal-content {
  animation: scroll-horizontal-root linear forwards;
  animation-timeline: --page-scroll;
  width: 400%;
  display: flex;
}

@keyframes scroll-horizontal-root {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(calc(-100vw * 3));
  }
} */

animation-timeline: scroll(self x);は、この要素自身の横スクロール量にアニメーションを連動させます。縦スクロールに連動させる場合は、scroll(root)scroll(ブロック要素のid)、あるいはscroll-timeline-nameで名前を定義したタイムラインを使用します。この機能は非常に強力ですが、実践で利用する際はポリフィル(一部のブラウザで機能を再現するJavaScriptコード)の利用や、JavaScriptでの代替実装も視野に入れる必要があるでしょう。

実際の表示

See the Pen css-horizontal-scroll-animation-07 by watashi-xyz (@watashi-xyz) on CodePen.

※ChromeもしくはEdge推奨

実装時に押さえるべき最適化とアクセシビリティ対応

CSS横スクロールアニメーションは、Webサイトの魅力を高める一方で、実装方法によってはパフォーマンスの低下やアクセシビリティの問題を引き起こす可能性があります。最高のユーザー体験を提供し、SEOの観点からも評価されるサイトを構築するためには、これらの側面を深く理解し、適切な対策を講じることが不可欠です。このセクションでは、モバイル対応、パフォーマンス最適化、そしてアクセシビリティの確保に焦点を当て、単に「動く」だけでなく、「高品質な」アニメーションを実装するための知見を提供します。

スマホ・タブレットで快適に動くレスポンシブな横スクロール設計

現代のWebサイトは、多様なデバイスで閲覧されることを前提に設計される必要があります。横スクロールアニメーションも例外ではなく、スマートフォンやタブレットなどのモバイルデバイスで快適に動作し、適切に表示されるようにレスポンシブ対応を行うことが重要です。

@mediaクエリを使ったレスポンシブ対応の基本的な考え方

@mediaクエリは、画面の幅や高さなどに応じて異なるCSSスタイルを適用するための基本的なツールです。これにより、デバイスの特性に合わせたレイアウトや表示を柔軟に切り替えることができます。

/* PCでのデフォルトスタイル */
.horizontal-section {
  display: flex;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  /* その他のスタイル */
}

.horizontal-item {
  flex: 0 0 30%; /* PCでは30%幅で3つ表示 */
  /* その他のスタイル */
}

/* スマートフォン向けのスタイル */
@media (max-width: 768px) {
  .horizontal-item {
    flex: 0 0 80%; /* スマホでは80%幅で大きく表示 */
  }
}

この例では、@media (max-width: 768px)を使って、画面幅が768px以下のデバイス(スマートフォンや小型タブレットなど)では.horizontal-itemの幅を80%に広げ、1つずつ大きく表示されるように調整しています。

画面幅に応じたwidthflex-basisgapなどの調整方法

  • flex-basis: display: flexの子要素の初期サイズを定義します。パーセンテージやvw(ビューポート幅)単位を使用することで、レスポンシブなアイテム幅を実現できます。
  • gap: display: flexdisplay: gridのアイテム間の余白を簡単に設定できます。モバイルではgapを小さくするなど、デバイスに応じた調整が有効です。
  • padding: スクロールコンテナのpaddingを適切に設定することで、コンテンツが画面の端に張り付きすぎるのを防ぎ、視覚的に快適な余白を確保します。

モバイルデバイスでのタッチ操作を考慮したscroll-snap-typeの活用と、オーバースクロールエフェクト(overscroll-behavior-x)の制御

  • scroll-snap-type: モバイルデバイスでは、指でスワイプしてスクロールすることが多いため、scroll-snap-typeは特に有効です。各コンテンツがきちんと停止することで、ユーザーはコンテンツ全体を快適に閲覧できます。
  • webkit-overflow-scrolling: touch;: iOSデバイスにおいて、慣性スクロールを滑らかにするためのプロパティです。多くの現代のブラウザでは不要になっていますが、古いiOSデバイスへの対応を考慮する場合に役立ちます。
  • overscroll-behavior-x: スクロール可能な領域の端に達したときに、親要素のスクロールが連動してしまう「スクロール連鎖」を防ぐために使用します。containnoneを設定することで、横スクロールコンテンツ内でのみスクロールが完結し、ページの縦スクロールに影響を与えないようにできます。
.scroll-container {
  /* ... */
  overscroll-behavior-x: contain; /* 横方向のスクロールチェインを抑制 */
}

SEOとパフォーマンスに配慮した軽量なアニメーションの作り方

アニメーションはWebサイトの魅力を高めますが、不適切な実装は表示速度の低下やブラウザの動作が重くなる原因となり、SEO評価にも悪影響を与える可能性があります。軽量でパフォーマンスに優れたアニメーションを実装するためのポイントを押さえましょう。

アニメーションがWebサイトの読み込み速度やパフォーマンスに与える影響

  • LCP (Largest Contentful Paint): ページの主要コンテンツが表示されるまでの時間。重いアニメーションはLCPを遅延させる可能性があります。
  • FID (First Input Delay): ユーザーが最初に行った操作(クリックなど)に対するブラウザの応答時間。アニメーションの負荷が高いと、この応答が遅れることがあります。
  • CLS (Cumulative Layout Shift): ページの読み込み中に予期せぬレイアウトのずれが発生する度合い。アニメーションによって要素の位置が大きく変動すると、CLSが悪化する可能性があります。

これらのCore Web Vitals指標は、GoogleのSEOランキング要因の一部であるため、パフォーマンスに優れたアニメーションはSEOにも貢献します。

will-changeプロパティの適切な利用法と注意点

will-changeプロパティは、要素の特定のプロパティが将来変更されることをブラウザに事前に伝えることで、ブラウザがその変更に備えて最適化を行うのを助けます。これにより、アニメーション開始時のカクつき(レンダリング負荷)を軽減できます。

.animated-element {
  will-change: transform, opacity; /* transformとopacityが変更されることを示唆 */
  /* transformとopacity以外のプロパティは書かない方が良い */
}

注意点: will-changeは乱用するとかえってパフォーマンスを悪化させる可能性があります。実際にアニメーションが発生する直前に適用し、アニメーションが終了したら削除するなど、必要な期間のみ適用するのがベストプラクティスです。常時適用すると、ブラウザが過剰なリソースを消費してしまう可能性があります。

transformプロパティがGPUで処理されやすいことの利点を強調

transformtranslateX, translateY, scale, rotateなど)やopacityプロパティは、ブラウザの合成レイヤーで処理されやすく、GPU(グラフィックス処理装置)の恩恵を受けやすい特性があります。これにより、CPU負荷を軽減し、より滑らかなアニメーションを実現できます。

一方で、width, height, top, left, margin, paddingなどのプロパティをアニメーションさせると、レイアウトの再計算や再描画が発生しやすいため、パフォーマンスに悪影響を与えやすいです。可能な限りtransformopacityを活用しましょう。

過度なアニメーションや複雑なパスを避けることの重要性

複雑すぎるアニメーションや、多数の要素を同時に動かすアニメーションは、たとえtransformを使っていてもパフォーマンスに影響を与える可能性があります。視覚的な効果とパフォーマンスのバランスを考慮し、本当に必要なアニメーションに絞り込むことが重要です。

アニメーション要素の数がパフォーマンスに影響すること

アニメーションさせる要素の数が増えれば増えるほど、ブラウザの処理負担も大きくなります。特にモバイル環境ではその影響が顕著に出やすいため、多数の要素を同時に動かす際は注意が必要です。

Chrome DevToolsなどを使ったパフォーマンス測定の簡単な紹介

Webサイトのパフォーマンスを測定するためには、Chrome DevToolsの「Performance」タブや「Lighthouse」機能が非常に役立ちます。これらのツールを使って、アニメーションがページの読み込み速度やレンダリングパフォーマンスに与える影響を分析し、ボトルネックを特定することで、具体的な改善策を講じることができます。

横スクロールUIにおけるアクセシビリティとデザインの工夫

魅力的なデザインだけでなく、誰もが利用しやすい「アクセシビリティ」を確保することは、現代のWebサイトにおいて不可欠です。横スクロールアニメーションを実装する際も、特定のユーザーがコンテンツにアクセスできない、または利用しにくいといった問題が発生しないよう、細やかな配慮が求められます。

キーボード操作でのナビゲーション(tabindexfocusスタイル)の重要性

マウスが使えないユーザーや、キーボード操作を主とするユーザー(例:視覚障がい者、運動機能障がい者など)のために、横スクロールコンテンツもキーボードで操作できるようにする必要があります。

  • tabindex: 要素がタブキーでのフォーカス順に含まれるかどうか、およびその順序を制御します。スクロール可能なコンテナや、カルーセル内の各アイテムなど、操作が必要な要素にtabindex="0"を設定することで、キーボードでのフォーカスが可能になります。
  • :focusスタイル: フォーカスされている要素には、明確な視覚的インジケータ(アウトラインなど)を提供し、ユーザーが現在どこにフォーカスがあるかを認識できるようにします。
.scroll-item:focus {
  outline: 2px solid dodgerblue; /* フォーカス時のアウトライン */
  outline-offset: 2px;
}

アニメーションの一時停止・再生ボタンの提供(JavaScriptが必要な場合も、必要性について言及)

自動で動き続けるアニメーションは、一部のユーザー(例:動くものが苦手な人、集中したい人)にとって煩わしい場合があります。このため、アニメーションを一時停止・再生できるボタンを提供することが、アクセシビリティ向上につながります。これは通常JavaScriptでの実装が必要ですが、CSSのanimation-play-state: paused;を切り替えることで実現可能です。

色のコントラスト、フォントサイズなど、視認性の高いデザインの重要性

アニメーションの有無にかかわらず、テキストやボタンの色と背景色のコントラスト比を十分に確保し、フォントサイズも適切に設定することで、弱視のユーザーや色覚特性を持つユーザーでもコンテンツを読みやすくします。

ユーザーがアニメーションを好まない場合の配慮(prefers-reduced-motionメディアクエリ)について解説

一部のユーザーは、ウェブサイト上の動きの速いアニメーションによって、めまいや吐き気などの体調不良を起こすことがあります。prefers-reduced-motionメディアクエリは、ユーザーがOSの設定で「動きを減らす」などの設定を有効にしているかどうかを検出し、それに合わせてアニメーションの表示を調整するためのものです。

/* デフォルトのアニメーション */
.animated-element {
  animation: slide 5s linear infinite;
}

/* ユーザーが動きを減らす設定をしている場合 */
@media (prefers-reduced-motion: reduce) {
  .animated-element {
    animation: none; /* アニメーションを無効化 */
    transition: none; /* トランジションも無効化 */
  }
}

このメディアクエリを使用することで、より多くのユーザーにとって快適なWebサイトを提供できます。

スクロールバーのカスタマイズ(scrollbar-width-webkit-scrollbar)によるデザイン性向上も触れる

デフォルトのスクロールバーはデザイン的にサイトと馴染まない場合があります。CSSでスクロールバーをカスタマイズすることで、UI全体の統一感を高めることができます。

  • scrollbar-width: Firefoxなどの一部ブラウザでスクロールバーの幅を制御します(auto, thin, none)。
  • webkit-scrollbar: Chrome, SafariなどのWebKit系ブラウザでスクロールバーの各部分を詳細にスタイルできます。
/* WebKit系ブラウザのスクロールバーをカスタマイズ */
.scroll-container::-webkit-scrollbar {
  height: 10px; /* スクロールバーの高さ */
}

.scroll-container::-webkit-scrollbar-track {
  background: #f1f1f1; /* トラックの背景色 */
  border-radius: 5px;
}

.scroll-container::-webkit-scrollbar-thumb {
  background: #888; /* サム(動く部分)の色 */
  border-radius: 5px;
}

.scroll-container::-webkit-scrollbar-thumb:hover {
  background: #555; /* ホバー時の色 */
}

よくある質問(FAQ)

ここでは、CSS横スクロールアニメーションに関するよくある疑問とその回答をまとめました。

CSSアニメーションとJavaScriptアニメーション(例:jQuery、GSAP)の使い分けは?

CSSアニメーション:

  • 得意なこと: シンプルな状態変化(ホバー時の色変化、要素の移動・拡大縮小・回転など)、パフォーマンスが重視されるアニメーション(ブラウザが最適化しやすい)、宣言的な記述でコードが簡潔になる。
  • 苦手なこと: 複雑なロジック(ユーザーの複雑なインタラクションに応じた動作)、スクロール量や要素の位置に厳密に連動するアニメーション(animation-timeline登場以前)、非同期処理を伴うアニメーション。

JavaScriptアニメーション (jQuery, GSAPなど):

  • 得意なこと: 複雑なシーケンスやタイムライン制御、スクロール量に応じた精密なアニメーション、複数の要素が連動する複雑な動き、DOM操作を伴うアニメーション。
  • 苦手なこと: CSSのみで実現できる簡単なアニメーションではオーバーキルになりがち、JavaScriptライブラリの読み込みによるパフォーマンスへの影響。

結論として、CSSのみで実現できる場合はCSSを優先し、より複雑な制御やインタラクションが必要な場合にJavaScript(特にGSAPのような高性能ライブラリ)の利用を検討するのがベストプラクティスです。

ブラウザごとの互換性や注意点はありますか?

一般的なCSSアニメーション(@keyframes, transform, animation:

現代の主要ブラウザ(Chrome, Firefox, Safari, Edge)ではほぼ問題なく動作します。ベンダープレフィックス(webkit-, moz-など)は古いブラウザ向けにはまだ役立ちますが、現代のCSS開発では必須ではなくなってきています。

scroll-snap-type:

主要ブラウザで広くサポートされていますが、一部の古いバージョンでは動作が異なる場合があります。

animation-timeline (view-timeline, scroll-timeline):

比較的新しい機能であり、現時点(2025年7月時点)では主要ブラウザでも完全にサポートされていない場合があります(特にSafari)。これを使用する際は、Can I use?などで最新のサポート状況を確認し、サポートされていないブラウザ向けのフォールバック(代替表示やJavaScriptでの実装)を考慮する必要があります。

スクロールバーのカスタマイズ:

webkit-scrollbarはWebKit系ブラウザ(Chrome, Safari, Edge)で有効ですが、Firefoxではscrollbar-widthscrollbar-color、IE/Edgeレガシーではms-overflow-styleなど、ブラウザごとにプロパティが異なります。

WordPressやReactで横スクロールアニメーションを実装するには?

WordPress:

  • テーマやブロックエディタ: 最近のWordPressテーマやGutenbergブロックエディタは、CSSクラスを追加する機能や、カスタムCSSを記述する機能を提供しています。記事で紹介したCSSコードを直接カスタムCSSとして追加することで実装可能です。
  • プラグイン: 横スクロールスライダーやカルーセルを簡単に実装できるプラグイン(例: Slider Revolution, Smart Slider 3など)も多数存在します。これらはCSSアニメーションだけでなく、JavaScriptも活用して高機能なスライダーを提供します。

React (Vue, Angularなどのフレームワーク含む):

  • CSSモジュール/Styled Components: Reactコンポーネント内でCSSを記述する方法として、CSSモジュールやStyled ComponentsのようなCSS-in-JSライブラリを使用するのが一般的です。これらの方法で、記事で紹介したCSSアニメーションをコンポーネントに適用できます。
  • フレームワーク特有のライブラリ: React向けには、より高度なアニメーションを実現するためのライブラリ(例: React Spring, Framer Motion)も存在しますが、本記事で紹介したCSSのみのアニメーションは、特別なライブラリなしでそのまま実装できます。CSSを直接適用するだけです。

横スクロールでアニメーションがカクつく場合の対処法は?

アニメーションがカクつく(スムーズでない)場合、以下の点を確認・対処してみてください。

  1. transformopacityの利用: width, height, top, leftなどレイアウトを再計算させるプロパティではなく、transformtranslateX, translateY, scale, rotate)やopacityプロパティをアニメーションに使用しているか確認してください。これらはGPUで処理されやすいため、パフォーマンスが高いです。
  2. will-changeの適切な使用: アニメーションされる要素にwill-changeプロパティを適用することで、ブラウザがレンダリングの最適化を行うのを助けます。ただし、乱用は避け、アニメーションが始まる直前に適用し、終わったら削除する(JavaScriptで制御)のが理想です。
  3. 複雑なCSSを避ける: box-shadowfilterのような計算コストの高いCSSプロパティをアニメーションさせると、パフォーマンスが低下しやすいです。
  4. 要素の数と複雑さ: 同時に多数の要素をアニメーションさせたり、非常に複雑なDOM構造を持つ要素をアニメーションさせたりすると、ブラウザに負荷がかかります。
  5. 画像サイズの最適化: アニメーションさせる画像が大きすぎないか確認してください。WebPやAVIFなどのモダンなフォーマットで圧縮し、適切なサイズに調整することが重要です。
  6. prefers-reduced-motionの活用: 動くものに敏感なユーザー向けに、アニメーションを簡略化したり無効にしたりするオプションを提供することも検討しましょう。
  7. ブラウザのデベロッパーツールでプロファイリング: Chrome DevToolsの「Performance」タブなどでアニメーションのボトルネックを特定し、原因を詳しく調査することで、具体的な改善点が見つかる場合があります。

まとめ

本記事では、CSSだけで実現できる横スクロールアニメーションについて、その基本的な構造から応用テクニック、そして実装時に考慮すべき最適化とアクセシビリティまで、幅広く解説しました。

  • 基本の理解: overflow-xscroll-snap-typeで快適な手動スクロールUIを、@keyframestransform: translateX()で自動アニメーションの基礎を学びました。
  • 目的別応用: 無限ループする画像ギャラリー、ユーザー操作に反応するインタラクティブスライダー、さらには縦スクロールと連動するパララックス風演出など、多様な表現をCSSのみで実現する方法をご紹介しました。特にanimation-timelineのような新しいCSSプロパティは、今後のWeb表現の可能性を広げます。
  • 品質向上: レスポンシブ対応によるモバイルデバイスでの快適な体験、transformwill-changeを活用したパフォーマンス最適化、そしてprefers-reduced-motionやキーボード操作への配慮といったアクセシビリティ対応の重要性を強調しました。

CSSは単なるスタイルシート言語ではなく、高度なアニメーションやインタラクションを構築するための強力なツールへと進化しています。JavaScriptに頼らずとも、魅力的な動きのあるWebサイトを作成できることをご理解いただけたのではないでしょうか。

この記事で提供したコピペ可能なサンプルコードを参考に、ぜひご自身のプロジェクトで横スクロールアニメーションを実践してみてください。ユーザーの目を引き、Webサイトのエンゲージメントを高めるために、今回学んだ知識を最大限に活用し、訪問者を魅了するようなWeb体験を創造してください。

あわせて読みたい

【2025年版】パララックス効果の作り方:CSSとJSで魅せるサイト+SEO対策まで
スクロールに応じて背景や画像が動く「パララックス効果」を、CSSやJavaScriptを使って実装する方法を初心者にもわかりやすく解説。CSSを使った基本テクニックから、Vanilla JSやGSAPによる滑らかな演出、さらにスマホ対応・SEO・表示速度に配慮した実装のコツまで網羅。実際に使えるコード例も紹介します。
Intersection Observerの使い方を徹底解説!遅延読み込み・無限スクロールからエラー解決まで
IntersectionObserverの使い方を基本から応用までやさしく解説。仕組みやscrollイベントとの違い、おすすめ設定パターン、画像の遅延読み込みやアニメーション表示、無限スクロール実装もサンプル付きでご紹介。発火しない原因や複数要素監視、スクロール方向検知など現場で役立つノウハウも網羅しています。
下スクロールで隠れ、上スクロールで表示!ヘッダーサイズ変更アニメーションの作り方【jQuery不要】
スクロールに応じてヘッダーを表示・非表示に切り替える方法を、初心者にもわかりやすく解説。JavaScript+CSSの実装コード付きで、UX向上やCV率改善のメリットも紹介します。モバイル対応や透過エフェクト、チラつき対策などの実践ポイントも網羅しているので、現場でそのまま使える内容です。
タイトルとURLをコピーしました