Webデザインを見ていて「これ、どうやって実装するんだろう?」と思うことはありませんか?
このブログシリーズ【このデザイン、どうコーディングする?】では、
日々の現場で見かけるモダンなUIデザインを、できるだけシンプルに、でも本質的に実装する方法を紹介していきます。
第1回となる今回は、スマホサイトでよく見かける横スライド型のカルーセルUIを、CSSだけで軽量に実装する方法を取り上げます。
それでは早速、完成イメージから見ていきましょう。
実装イメージ&HTML構造
まずは今回実装するカルーセルUIの完成イメージと、基本のHTML構造を確認しておきましょう。
最小限のマークアップで、柔軟性のあるレイアウトが可能です。
基本パターン:16:9 カードの横スライド
横方向にスワイプできる、比率固定・スナップ付きのカルーセルUIです。
以下のようなカードが横並びでスクロールされ、CSSだけで完結します。
<div class="carousel">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
</div>
.carousel
:全体の横スクロールコンテナ.card
:中身のカード(1枚ずつ表示)
今回はより意味のある構造を意識し、実際の用途に応じて以下のようなHTMLも使えます
<ul class="carousel">
<li class="card">
<img src="..." alt="..." />
<h3>タイトル</h3>
<p>説明文など</p>
</li>
<li class="card">...</li>
</ul>
ul
+li
:リスト形式でセマンティクスを保ちたい場合に有効- カード内に画像、テキストを含めても構造はシンプル
応用例:3枚同時に表示するマルチ表示型
より一覧性を重視したい場合は、1画面に複数枚のカードを並べるパターンも有効です。
<div class="carousel">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
</div>
この場合は、後述するCSSで .card
に width: calc((100% - gap) / 3)
のような指定を行います。
補足:スクロールスナップに対応した最小構造のポイント
.carousel
にoverflow-x: auto
を指定して横スクロールを可能に.card
にscroll-snap-align
を付けて、スナップポイントを定義- 子要素は
flex
で横並びにしつつ、aspect-ratio
で比率を固定
完成CSSスタイル
今回のカルーセルUIを実現するための完成CSSは以下のようになります。
コピペしてすぐに試せるよう、最低限のスタイルに絞りつつ、実用的な仕様になっています。
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 1rem;
padding-inline: 1rem;
scroll-padding-inline: 1rem;
-webkit-overflow-scrolling: touch;
scrollbar-width: none; /* Firefox */
}
.carousel::-webkit-scrollbar {
display: none; /* Chrome, Safari */
}
.card {
flex: 0 0 auto;
width: clamp(250px, 80%, 400px);
aspect-ratio: 16 / 9;
scroll-snap-align: start;
background: #eee;
border-radius: 12px;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
color: #333;
}
スタイル構成のポイント
.carousel
:横スクロールの設定、スナップ、スクロールバー非表示など.card
:比率固定、スナップポイント、デザイン要素(影・角丸など)
実装Tips・詳細解説
それでは、上記のCSSの中から、実装上で特に重要なプロパティや技術的ポイントをピックアップし、それぞれの意図や応用のヒントを紹介します。
CSSの進化により、こうしたUIがJSなしで作れる時代になってきましたが、大切なのは細部の設計力です。
ここでは、単なる「動くUI」を超えて、実装中によくある疑問や細かい配慮ポイントに重点を置いて解説します。
横スクロールの基本構造とスナップ挙動
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
}
.card {
flex: 0 0 auto;
scroll-snap-align: start;
}
ポイント
overflow-x: auto
:横方向のスクロールを有効化flex
+flex: 0 0 auto
:子要素(カード)を横並び&幅固定にscroll-snap-type: x mandatory
:X軸でスナップ(必須で止まる)scroll-snap-align: start
:カードの左端が親の左端に吸着する
注意点:
scroll-snap-type
は Safari(特にiOS)でやや挙動が違うことがあるため、実機検証推奨- スナップが効かない場合は、子要素の
scroll-snap-align
が設定されているか、親のoverflow-x
とdisplay: flex
が正しいかを確認
aspect-ratio による比率固定
.card {
aspect-ratio: 16 / 9;
}
ポイント
aspect-ratio
により、高さが自動計算されて比率を維持します- 今回は「16:9」で映像や画像カードに適した黄金比
応用Tips:
aspect-ratio: 1
→ 正方形カードにも応用可(SNS風UIなど)- 画像の
object-fit: cover
と併用することで、枠にフィットしたサムネイル表現が可能
clamp() による柔軟な幅指定
.card {
width: clamp(250px, 80%, 400px);
}
ポイント
- **最低250px・最大400pxの範囲で、理想は80%**という、柔軟かつ制御可能なサイズ指定
- デバイス幅に応じて自然にサイズが調整されるため、メディアクエリなしでレスポンシブ対応
注意点:
clamp()
は IE 非対応(現在では問題ないがレガシー対応時は注意)
-webkit-overflow-scrolling: touch の効果
.carousel {
-webkit-overflow-scrolling: touch;
}
ポイント
- iOSでネイティブに近いスムーズなスクロールを実現
overflow-x: auto
単体では滑らかにならないため、iOS対応ではほぼ必須
スクロールバーの非表示とその判断
.carousel {
scrollbar-width: none; /* Firefox */
}
.carousel::-webkit-scrollbar {
display: none; /* Chrome, Safari */
}
ポイント
- 見た目をシンプルにしたい時に有効
- ただしアクセシビリティ的には議論があるため、状況に応じて表示させるのも選択肢
代替案:
スクロールバーは表示しつつ、薄めのスタイルにカスタマイズする手もある(例:透明度調整)
アニメーション・ホバー効果の拡張
.card {
transition: transform 0.3s ease;
}
.card:hover {
transform: scale(1.03);
}
ポイント
- シンプルなホバー時の拡大効果でインタラクティブ感を追加
:hover
はPC向け、タッチ環境向けには:focus-visible
や:active
を併用すると◎
まとめ・応用のヒント
今回紹介したCSSカルーセルは、軽量で実装もシンプルなわりに、表現の幅が広く、さまざまなUIに応用できます。
特にaspect-ratio
やscroll-snap
など、モダンなCSS機能を組み合わせることで、これまでJavaScriptに頼っていたパターンが、JSなしで完結するのは非常に大きなメリットです。HTMLもCSSも最小限で済むため、保守性・パフォーマンスの両面で優秀な選択肢になります。
さらに応用すれば、以下のような場面にも自然に展開できます。
- SNSフィード風の水平カードUI(
aspect-ratio: 1
で正方形に) - 時系列イベントのタイムライン(カード内に日時や進行情報を入れるだけ)
- フィルター付きの横スクロール一覧(ボタン操作で
scrollLeft
を動かせばJS併用もOK) - ギャラリーやスライダー系UIのラフ実装(プレゼン資料のモックなどにも便利)
細かいデザイン調整や動きの強化にはJSやライブラリも必要になりますが、「とりあえず動くUI」「試作を早く見せたいUI」にはCSSだけでここまでできるというのは、日々の開発で武器になるはずです。
今回のTipsが、少しでもコーディングのヒントや発想のきっかけになれば嬉しいです。
次回もお楽しみに!