scroll-behaviorがうまく動かなかったことと分かってなかったこと

CSSのscroll-behaviorプロパティを使うとスムーススクロールができるようになってるらしい。
まだまだサポートされているブラウザが少ない(今時点でじゃFirefoxとGoogle Chromeだけ)ようなので、すぐにいろんなサイトで利用するのはまだ早いかもしれないけれど、いつ使うようになってもいいようにサンプルを作ってみた。
けど、うまく動かなかった、ということで一考察。

まず初めにscroll-behaviorプロパティって何かを引用しておく。

CSS の scroll-behavior プロパティは、ナビゲーションや CSSOM のスクローリング API によってスクローリングボックスにスクロールが発生した際の、そのスクロールの振る舞いを指定します。
scroll-behavior – CSS: カスケーディングスタイルシート | MDNより

動作サンプル

サンプルは簡単にセクションが3つ、ヘッダーにあるメニューをクリックするとスルスルとそのセクションまでスクロールしていくイメージ。

HTML

<body>
    <header>
        <nav>
            <a href="#section-01">Section01</a>
            <a href="#section-02">Section02</a>
            <a href="#section-03">Section03</a>
        </nav>
    </header>
    <main class="scroll-container">
        <section id="section-01">
            <p>section-01</p>
        </section>
        <section id="section-02">
            <p>section-02</p>
        </section>
        <section id="section-03">
            <p>section-03</p>
        </section>
    </main>
    <footer>
        footer
    </footer>
</body>

CSS

以下は装飾の部分なので適宜変更してほしい。

body {
    text-align: center;
}

nav {
    display: flex;
    justify-content: center;
}

nav a {
    margin: 1rem;
    padding: .5rem;
}

section {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

#section-01 {
    background-color: #999;
}

#section-02 {
    background-color: #777;
}

#section-03 {
    background-color: #555;
}

プラスこれが動かなった時のコード。

.scroll-container {
    scroll-behavior: smooth;
}

.scroll-containerscroll-behaviorを設定しても期待したスクロールは起こらなかった。
飛び先(id属性)を持つ要素の親要素(先祖要素)にscroll-behaviorを設定すればいいということかと思ってたけど、どうも違うみたい。

動作できるようにする

とりあえず動作だけさせてみると、動かなかった時のコードをやめて、

/* 例1 */
html {
    scroll-behavior: smooth;
}

もしくは、

/* 例2 */
.scroll-container {
    scroll-behavior: smooth;
    height: 100vh;
    overflow-y: scroll;
}

にするとスクロールするようになった。

例1) html要素に設定

この例1のhtml要素に設定したほうが、当初のイメージに近い動作をする。

例2) .scroll-container要素の設定を増やす

この場合は見え方がそもそも変わってしまう。
.scroll-containerに明示的に高さを指定し、その中で親要素““.scroll-containerよりも高さのある子要素section“`がスクロールする。

さてこの2つから考えるに、なぜ最初のコードではスクロールしなかったのか。

スクローリングボックスにscroll-behavior

失敗したコードと、動作した2つのコードを考えているうちに、どうもそもそも大きな勘違いをしていたことに気がついた。

ここで引用を再度引く。

スクローリングボックスにスクロールが発生した際の、そのスクロールの振る舞いを指定します。

scroll-behaviorプロパティは、スクローリングボックスに対して設定した際のスクロールを制御するもので、「スクローリングボックスにスクロールが発生した際の」という部分、もっといえば「スクローリングボックス」という部分のことをよくわかっていなかったのだ。
MDNのサイトの仕様からリンクされているページから引用する。

Elements and viewports have an associated scrolling box if has a scrolling mechanism or it overflows its content area and the used value of the overflow-x or overflow-y property is hidden. [CSS3-BOX]

An element body (which will be the HTML body element) is potentially scrollable if all of the following conditions are true:
body has an associated CSS layout box.

body’s parent element’s computed value of the overflow-x or overflow-y properties is neither visible nor clip.

body’s computed value of the overflow-x or overflow-y properties is neither visible nor clip.
CSSOM View Moduleより

なんとなくGoogle翻訳で訳したニュアンスだけ拾って読んでいくと、overflowが設定してあったりしてスクロールできるようになっている要素。ちょっと説明が雑になってしまいそうなので、例をもとに考えてみる。

例2を考えるとイメージしやすい。
例2では.scroll-containerに明示的に高さを指定し、さらにoverflow-y: scrollによりスクロールするボックス(ここでいうボックスはエリア、程度の意)であることを指定している。
つまりこれで.scroll-containerが「スクローリングボックス」であることを明らかにしたので、scroll-behavior: smooth;は期待通りにスムーススクロールしてくれた、ということだろう。

ではなぜ例1でもスムーススクロースは発生するのか。
上記引用ページの同じ箇所に、次のような文章があった。

The HTML body element is the first body HTML element child of the root HTML element html.
CSSOM View Moduleより

body要素がHTMLのルートのhtml要素にとって一番はじめの要素で、html要素にscroll-behavior: smooth;を設定した場合(htmlをスクローリングボックスにした場合)には、body要素以下のアンカーにはスクロールすることができるようになる。
おそらくそもそもhtml要素自体がそもそもスクローリングボックス的な性質を持っている、つまりbody要素が画面以上の高さを持つ場合にデフォルトでスクロールバーが表示される、からっていうことなんじゃないかと思った。

反対例として適切かどうか微妙だが、最初の状態で、body要素にscroll-behavior: smooth;を設定してもスムーススクロールは起こらない。
この辺のことは「CSS-Tricks」のデモを見てようやく気がつくことができた。

これまではJavascriptで実装しきたものがどんどんCSSだけでできるようになっていく。
スムーススクロールなんて当然のようにjQueryで実装してきた。
Webが閲覧にはスマホがメインになったり、PCでもレイアウトが多様化したりしていて、スムーススクロールに関してはどこまで必要性があるのか考える必要があるし、そのページによるといった面も大きい。
逆説的にサポートブラウザの少ない今なら、サイトによってはサポートブラウザのみCSSで実装する、ということになってもさほど不便はない、ということもできるだろう。
管理がメインになってコード書く機会が減っていきているけど、それでもやっぱり新しい知識はインプットしていかないとなぁとつくづく思う。

参考サイト

カテゴリー: CSS