LoginSignup
16
19

More than 5 years have passed since last update.

打倒slick! CSS Scroll Snap入門

Last updated at Posted at 2018-11-02

はじめに

2, 3ヶ月ほど前、勧告候補である「CSS Scroll Snap Module Level 1」のプロパティ群が、Google Chromeで使用できるようになりました:tada:

いったいどんなことが出来るのか、気になります。そこで、さっそく使ってみました。この記事は、その際のメモです。

用意したものは、最新版のGoogle Chrome(バージョン: 70.0.3538.77)です。

CSS Scroll Snap とは

CSS Scroll Snap は、スクロール可能な領域内のスクロール位置を調整できる機能を提供してくれるようです。

私たちは、Webページから目的の内容を探し出すとき、スクロールをしながら、セクション内の文章を読みます。
そして、目的の内容が見つかると、スクロールを止めます。

その時に「あっ、スクロールしすぎちゃった。最初から読むためにスクロール位置を調整しなきゃ...。」なんてことがよく起こると思います。これは急いでいるときには特に煩わしい作業です。

そこで、そんな作業をしなくても済むように、CSS Scroll Snap を使うことが出来ます。これを使えば、スクロール操作が完了した後に、スクロール位置を指定した場所まで調整してくれるのです。

押さえておくべきプロパティ

  • scroll-snap-typeプロパティ
  • scroll-snap-alignプロパティ
  • scroll-paddingプロパティ
  • scroll-marginプロパティ

CSS Scroll Snapを使うなら、とりあえずこの4つを押さえておけば良いかな、と思います。

scroll-snap-typeプロパティ

scroll-snap-typeプロパティは、

  • スクロール位置の調整を行うかどうか
  • どの軸でスクロール位置を調整するか
  • どの程度厳密に調整するか

を指定します。
このプロパティは、スクロール可能な領域(スクロールコンテナ)に対して設定します。

スクロール位置の調整を行うかどうか

スクロール位置の調整を行わない場合、このプロパティにはnoneを設定します。これが初期値です。

どの軸でスクロール位置を調整するか

  • x: X 軸でスクロール位置の調整を有効にする
  • y: Y 軸でスクロール位置の調整を有効にする
  • block: ブロック軸でスクロール位置の調整を有効にする
  • inline: インライン軸でスクロール位置の調整を有効にする
  • both: X, Y 軸両方でスクロール位置の調整が行われる

どの程度厳密に調整するか

  • mandatory: スクロール位置を調整できる場合、スクロール位置が調整される
  • proximity: スクロール位置を調整でき、調整後のスクロール位置が現在位置から近い場合は、スクロール位置が調整される。そうでない場合、スクロール位置の調整は行われない。

使用例

これらの設定は結構重要なのですが、言葉だけでは伝わりにくい部分があるので、簡単な例を用意しました。
調整の厳密さに関する指定であるmandatoryproximityを並べて、比較できるようにしています。
最新版のGoogle Chromeであれば動作すると思うので、ぜひ実際に試してみてください(動作確認リンク)。

両方ぐりぐり弄っているとわかると思いますが、mandatoryでは絶対にスクロール位置の調整が行われるのに対して、proximityではスクロール位置の調整が行われない位置があります

<div class="container">
  <div class="scroll-container">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=mandatory1" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=mandatory2" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=mandatory3" alt="">
  </div>

  <div class="scroll-container proximity">
    <img src="http://placehold.jp/703d40/ffffff/450x450.png?text=proximity1" alt="">
    <img src="http://placehold.jp/703d40/ffffff/450x450.png?text=proximity2" alt="">
    <img src="http://placehold.jp/703d40/ffffff/450x450.png?text=proximity3" alt="">
  </div>
</div>
.container {
  display: flex;
}

.scroll-container {
  display: flex;
  flex-basis: 50%;
  flex-direction: column;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  max-height: 100vh;
}

.proximity {
  scroll-snap-type: y proximity;
}

img {
  scroll-snap-align: start;
  margin-bottom: 5px;
}

scroll-snap-alignプロパティ

scroll-snap-alignプロパティでは、

  • スクロール位置の調整を行うかどうか
  • スクロールコンテナ内の可視領域(スナップポート)にある要素をどのように配置するか

を指定します。
このプロパティは、スクロール可能な領域の子要素に対して設定します。

スクロール位置の調整を行うかどうか

  • none: noneを指定したコンテンツでは、スクロール位置の調整が行われない。つまり、スクロールが調整される場合、そのコンテンツの隣にあるコンテンツにスクロールされる。動作確認リンクを用意した。これを実行すると、2つ目のimg要素にスクロールが調整されないことがわかる
  • start: スクロールコンテナ内で可視領域にある要素の始端が、スクロールコンテナの始端に位置するように、スクロール位置が調整される
  • end: スクロールコンテナ内の可視領域にある要素の終端が、スクロールコンテナの終端に位置するように、スクロール位置が調整される
  • center: スクロールコンテナ内の可視領域にある要素の中央が、スクロールコンテナの中央に位置するように、スクロール位置が調整される

使用例

こちらも、言葉だけではいまいちわからないと思うので、例を用意しました(動作確認リンク)。
scroll-snap-alignプロパティに、start, end, centerを指定した時の比較をしています。

この例を実行してみるとわかると思いますが、startを指定すると、スクロールコンテナの上端にスクロール位置が調整されるようになります。center, endを指定した場合も、それぞれスクロールコンテナの中央、下端にスクロール位置が調整されます。

<div class="container">
  <div class="scroll-container start">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=start1" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/250x250.png?text=start2" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=start3" alt="">
  </div>

  <div class="scroll-container end">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=end1" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/250x250.png?text=end2" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=end3" alt="">
  </div>

  <div class="scroll-container center">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=center2" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/250x250.png?text=center1" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=center3" alt="">
  </div>
</div>
.container {
  display: flex;
}

.scroll-container {
  display: flex;
  flex-basis: 33.3%;
  flex-direction: column;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  max-height: 100vh;
}

img {
  margin-bottom: 5px;
}

.start img {
  scroll-snap-align: start;
}

.end img {
  scroll-snap-align: end;
}

.center img {
  scroll-snap-align: center;
}

scroll-paddingプロパティ

scroll-paddingプロパティは、

  • スクロールコンテナ内にpaddingを設定するかどうか

を指定できます。

scroll-paddingプロパティについては、例を使いながら説明をします。
たとえば、このような固定ヘッダーがあるページで、CSS Scroll Snapを使用した場合を考えます。

<div class="container">
  <header></header>
  <div class="scroll-container start">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=start1" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/250x250.png?text=start2" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=start3" alt="">
  </div>
</div>
body{
  margin:0;
}

.container {
  display: flex;
}

header {
  position: fixed;
  width: 100vw;
  height: 100px;
  background: rgba(255,0,255,.3);
  top: 0;
  left: 0;
}

.scroll-container {
  display: flex;
  flex-direction: column;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  max-height: 100vh;
  scroll-padding-top: 150px;
}

img {
  margin-bottom: 5px;
}

.start img {
  scroll-snap-align: start;
}

従来の方法であれば、padding-topを固定ヘッダーの高さ分設定することで、固定ヘッダーの部分に余白が作られ、コンテンツ全体が表示されるようになります。

しかし、CSS Scroll Snapを使用すると、padding-topを設定していても、スクロール位置を調整する際にpaddingを無視したスクロール位置の調整が行われます

こちらはpadding-topのみを設定したときの例です。一度スクロールすると、スクロール位置の調整が行われ、padding-top分を無視したスクロール位置の調整が行われることがわかると思います。

<div class="container">
  <header></header>
  <div class="scroll-container start">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=start1" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/250x250.png?text=start2" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=start3" alt="">
  </div>
</div>
body {
  margin: 0;
}

.container {
  display: flex;
  max-height: 100vh;
}

header {
  position: fixed;
  width: 100vw;
  height: 100px;
  background: rgba(255, 0, 255, 0.3);
  top: 0;
  left: 0;
}

.scroll-container {
  display: flex;
  flex-direction: column;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  max-height: 100vh;
  padding-top: 100px;
}

img {
  margin-bottom: 5px;
}

.start img {
  scroll-snap-align: start;
}

この動作を防ぐために、scroll-paddingプロパティを使うことができます。
scroll-paddingプロパティを使うことで、スクロール位置の調整にもpaddingが考慮されるようになります。

scroll-paddingプロパティを使った時の動作はこのようになります

<div class="container">
  <header></header>
  <div class="scroll-container start">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=start1" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/250x250.png?text=start2" alt="">
    <img src="http://placehold.jp/3d4070/ffffff/450x450.png?text=start3" alt="">
  </div>
</div>
body {
  margin: 0;
}

.container {
  display: flex;
  max-height: 100vh;
}

header {
  position: fixed;
  width: 100vw;
  height: 100px;
  background: rgba(255, 0, 255, 0.3);
  top: 0;
  left: 0;
}

.scroll-container {
  display: flex;
  flex-direction: column;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  max-height: 100vh;
  padding-top: 100px;
  scroll-padding-top: 100px;
}

img {
  margin-bottom: 5px;
}

.start img {
  scroll-snap-align: start;
}

scroll-marginプロパティ

scroll-marginプロパティは、

  • スクロールコンテナに対するmarginを設定するか

を指定できます。
(※このプロパティの動作については、十分に理解できていないので、この部分は改めて追記する予定です。)

ブラウザの対応状況

Can I use によると、Google Chrome, Safari はCSS Scroll Snapをサポートしているようですが、その他のブラウザでのサポートはまだ十分ではありません。また、現在の段階ではGoogle Chrome, Safari間の実装にも差異がある可能性が残っているため、注意が必要です。

以上。

16
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
19