CSSだけでiOS Safariスクロールバー非表示に対処する新しいやり方

# iOS safariの暴虐

iOS safariでは、スクロールできる要素に対してスクロールバーを表示しないという正気を疑う挙動をします。
現代は端末幅にあわせてコンテンツの幅を柔軟に調整するのが一般的需要ですから、画面幅によっては運悪くちょうどキリのいいところで文章が切れてしまうことは十分にありえます。そんな場合、ユーザーはその要素がスクロール可能だとはまるで気づきません。

もちろん、iOSを使っている人間はそういう不自由さを受け入れる覚悟があるからApple製品を使っているのです。愛の前では使いにくいことなんて何の障害にもなりません。
しかしサービス運営者としては困りものです。Appleなんか好きでもなんでもなくても、そういう暴虐の限りを尽くした挙動にも対応できなければ「使いにくい」っつって文句言われたり、コンバージョン率が落ちたり、ビジネス的な損失につながるのです。無視したくても無視できないのです。はいうんこ〜💩

以前は `::-webkit-scrollbar` をつかってどうにかすることができていました。
でも[Safari 13](https://developer.apple.com/documentation/safari-release-notes/safari-13-release-notes#3314682)において慣性スクロールがデフォルトになったことで、その対策も使えなくなりました。がーん😱
とりぷるうんこ〜💩💩💩

# 既存の対策

それに対するよくある対策はJSを使うものです。スクロールイベントを拾ってきて無理やりスクロールバーもどきを作ります。
このようなやり方は無駄なリソースを必要とするので、💩神奈川県警💩などに「不正指令電磁的記録に関する罪」の名目で拘束されるリスクがあります。
また、採用しているウェブフロントエンドフレームワークとの相性なども考えなくてはなりません。

その他、[なんか指のイラストを表示してしゅ〜しゅ〜と動かして「スクロールできます」とか表示する手法](https://appleple.github.io/scroll-hint/#demo)もあります。でも、結局JSを使っていて上記と同じ問題をはらんでいたり、スクロールバーを表示するのと比較してなんとも自己主張が激しく過剰です。「目立たせる」という手法は、もっとも重要な1つ2つだけの部分だけに使うべきです。さもなければユーザーは結局すべてを見ないようになってしまいます。目立つことばかり考える邪悪なクソ💩ウェブ広告がうざがられるだけだったり、バカの1つ覚えみたいなポップアップ通知を読まずに閉じられてしまうのはよくあることではないでしょうか？

# 提案手法

そのような現状に対して、新しい対策を提案します。

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="PodLvyj" data-user="arowM-the-reactor" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/arowM-the-reactor/pen/PodLvyj">
  Untitled</a> by Sakura-chan the goat (<a href="https://codepen.io/arowM-the-reactor">@arowM-the-reactor</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

スクロール可能な要素の下部に控えめな影を入れています。最後までスクロールするとこの影は消えて「スクロールし終わった」という視覚的フィードバックが与えられます。

そして重要なのは、この効果をCSSだけで実現できていることです。影の濃さなども容易に変更することができます。その要素の重要度に応じて目立たせ方を調整することもできるのです。

# 技術解説

HTMLはとくに特殊なことをしていません。コンテンツを`div`で囲んだだけです。

```html
<div class="scrollable">
  <p>ヤギとは魅力に溢れた生き物である。</p>
  <!-- (中略) -->
</div>
```

ポイントはCSSです。ここではSCSS記法を採用します。

```scss
$base-color: #ddc9e7;

.scrollable {
  overflow-y: auto;
  /* (中略) */

  /* 下部に影をつけて続きがある感じを演出する */
  box-shadow: inset 0em -0.9em 0.8em -18px;

  /* 最下部までスクロールされた際、この要素が影の上に重ねて表示されることで、影が消えたように見える */
  &::after {
    content: '';
    display: block;
    position: relative;
    z-index: 1000;
    height: 0.8em;
    background-color: $base-color;
    /* scrollable に 0.2em のpaddingがついており、そのままだと左右に 0.2em ぶん隙間ができて影が見えてしまう。それを防ぐためのマイナスマージン。*/
    margin: 0 -0.2em;
  }
}
```

まずは`box-shadow`。これによって下部の影をつけています。これは別に大したテクニックでもなんでもないですね！

次に `::after` 疑似セレクター。これは、最下部までスクロールされたときに上記の影を消すためのテクニックです。
別に何ら難しい原理ではありません。z-indexが大きい要素をコンテンツの下に用意しておき、最後までスクロールされたらその要素が影よりも上に表示されることで影を隠しているだけです。

もちろん細かいことを言えば、これではゆ〜っくりスクロールしたときに「影が下から消える」という直感に反した挙動を示します。でも、そんなにゆ〜っくりスクロールする人なんていません。人間さんはあくせく生きてるからね。さくらちゃんはヤギさんだからのんびりお日様の下で反芻した草をくっちゃくっちゃ噛み締めてるよ🐐
何を隠そうあなた自身も、最初の例を試したときには気づかなかったんじゃないですか？

このように、本手法を用いることで、HTMLに変更を加える必要もなく、人工のJSを一切使わず、天然由来の最小限のCSS成分だけで解決できました。

ぶっめいぇ〜い！🎉

[さくらちゃんの追悼写真集を手に入れる](https://amzn.to/38DyjWr)
[さくらちゃんをもっと見る](https://twitter.com/hashtag/%E3%81%95%E3%81%8F%E3%82%89%E3%81%A1%E3%82%83%E3%82%93%E6%97%A5%E8%A8%98?src=hash)
[他の記事を見る](https://qiita.com/arowM)

![eyecatch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16345/fa9d5a73-bb43-1643-10f0-856432cd7e13.jpeg)