スマホサイトでよく見かける、横スクロールUIの簡単な作り方。
JavaScriptは使わず、CSSだけで実装します。
要素を改行させずに横一列へ並べ、画面幅に収まらない部分はそのまま画面外にはみ出させます。
パンくずリスト、タグ一覧、カードレイアウト、横並びメニューなどでよく見かけるアレです。
See the Pen CSSだけで作る、横一列の「はみ出しスクロール(スワイプ)」 by MEMORUKA (@memoruka) on CodePen.
※スマホ実機での閲覧を推奨
デモコード
.parent {
overflow-x: auto;
}
.flex {
display: flex;
flex-wrap: nowrap; /* 改行させない */
width: max-content; /* 中身の横幅に合わせる */
}
.flex__item {
flex-shrink: 0; /* 縮まずに要素の幅を確保する */
}<div class="parent">
<ul class="flex">
<li class="flex__item">
横並びアイテム 1
</li>
<li class="flex__item">
横並びアイテム 2
</li>
<li class="flex__item">
横並びアイテム 3
</li>
</ul>
</div>※要所のみ抜粋
プロパティの役割解説
overflow-x: auto;
親要素に指定。
横幅に収まりきらず、はみ出した部分をスクロールできるようにします。
スマホでは、横方向にスワイプして表示できます。
flex-shrink: 0;
display: flex; の中身が縮むことを防止する。flex の子要素は、デフォルトでは親要素の幅に収まるように縮もうとするので、これを防止。
ちなみに flex: 0 0 auto; と書いても可。ショートハンドの中身は、
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;です。つまり、伸びない。縮まない。幅はwidthや中身に合わせる……という指定です。
flex-wrap: nowrap;
さらに横並びの要素の改行(折り返し)も防止。
一応、display: flex; の初期値は nowrap なので、別に書かなくても良いけど、明示する意味では、書いておくと分かりやすいです。
width: max-content;
これが大事。
親要素の幅を「中身が横に並んだ時の長さ」に自動で計算させる。
通常、ブロック要素は親要素の幅いっぱいに広がろうとしますが、max-content を指定することで、内在的な最大サイズ、つまり「中身が改行せずに並んだ場合に必要な幅」を自動で計算します。これにより、例えば .flex__item が10個あれば、10個分の横幅に合わせて .flex の幅が自動で決まります。
このプロパティのおかげで、横スクロールの終点を中身の幅に合わせやすくなります。
要素の数が増減しても、JavaScriptで幅を計算する必要は無く、HTMLを追加・削除するだけで、スクロールできる範囲も自然に追従します。CMS等とも相性が良い。
実装を想定したスマホデモ
See the Pen CSSだけで作る、横一列の「はみ出しスクロール(スワイプ)」 by MEMORUKA (@memoruka) on CodePen.
※スマホ実機での閲覧を推奨
.main-container {
--margin: 30px;
padding-inline: var(--margin);
margin-inline: auto;
}
.wrapper {
position: relative;
&::after {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
display: block;
width: var(--margin);
height: 100%;
background: linear-gradient(to right,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, .7) 50%,
rgba(255, 255, 255, .9) 100%);
transform: translate(100%, 0);
}
}
.parent {
position: relative;
overflow-x: auto;
margin-right: calc(-1 * var(--margin));
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
.flex {
display: flex;
flex-wrap: nowrap;
width: max-content;
padding-right: var(--margin);
gap: 10px;
line-height: 1;
}
.flex__item {
flex-shrink: 0;
}<div class="main-container">
<div class="wrapper">
<div class="parent">
<ul class="flex">
<li class="flex__item">
<img src="thumbnail_1.jpg" alt="サムネイル 1">
</li>
<li class="flex__item">
<img src="thumbnail_2.jpg" alt="サムネイル 2">
</li>
<li class="flex__item">
<img src="thumbnail_3.jpg" alt="サムネイル 3">
</li>
</ul>
</div>
</div>
</div>※コードは要所のみ抜粋
実際にサイトに組み込むとしたら、こんな感じでしょうか。
CodePenには「パンくずリスト」と「サムネイル一覧」に横スクロールUIを組み込んでみました。
::after
右側にもコンテンツが続いていることを分かりやすくするため、スクロール領域を包む外側の親要素に、疑似要素でグラデーションを重ね、右端に配置しています。「右側にまだ続きがある」ということを視覚的に伝えやすくする工夫です。
scrollbar-width: none;
スクロールバーは、一応CSSで消しましたが、そもそもスマホ実機では消えるので基本は放ったらかしで良し。むしろ消してしまうと、PCのマウス操作では、スマホのように直接「掴む」ことが出来ないので、スクロールバーが無いと操作性が悪いです(一応、ホイール操作でスクロール自体は出来る)。
基本的にこのUIは、スマホ向けに限定するのがおすすめですが、PCでも操作させたい場合は、スクロールバーを表示しつつ、見た目が気になるならばCSSでカスタマイズすれば良いと思います。
現場からは以上です。















