有名サイトで使用されているCSSテクニックまとめ

昨今のフロントエンドのCSS開発においては、タスクランナーやフレームワークの活用により煩雑なベンダープレフィックスの付与を意識する必要がありませんし、IE11のサポート終了により実戦に投入できるCSSプロパティも格段に増えました。
たった数行の記述で複雑な機能が実装可能だったり、再現が難しかったデザインへも対応できるようになったことは喜ばしいことです。
そこで今回は有名サイトで実装されているそんな最新のCSSテクニックをあらためて確認してみたいと思います。

:::note warn
以下で引用しているサイトは2022年9月7日現在に確認したものであり、それ以降は更新により変更されている可能性があります。
:::

# 「Apple」のすりガラス風グロナビ
https://www.apple.com/jp/

<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html,result" data-slug-hash="VwXJEwa" data-user="p_toro" 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/p_toro/pen/VwXJEwa">
  すりガラス</a> by p_toro (<a href="https://codepen.io/p_toro">@p_toro</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```scss
backdrop-filter: saturate(180%) blur(20px);
```
[backdrop-filter - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/backdrop-filter)
["backdrop-filter" | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/?search=backdrop-filter)

**saturate** → 入力画像の彩度を上げたり下げたりします。
**blur** → 入力画像にガウシアンぼかし（ガウス関数をもちいて画像をぼかす処理）を適用します。

:::note info
- saturateで調整することにより、鮮やかな印象になっています。
- 現在は-webkit-のプレフィックスが必須です。
- Firefox（104.0）ではblurは効いているものの、saturateは適用されていませんでした。
:::

***
# 「apple」のグラデーションテキスト
https://www.apple.com/jp/macbook-air-m2/

<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html,result" data-slug-hash="poLMXGg" data-user="p_toro" 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/p_toro/pen/poLMXGg">
  グラデーションテキスト</a> by p_toro (<a href="https://codepen.io/p_toro">@p_toro</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```scss
background-clip: text;
-webkit-text-fill-color: transparent;
```
[background-clip - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/background-clip)
[Background-clip: text | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/background-clip-text)

[-webkit-text-fill-color - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/-webkit-text-fill-color)
[CSS property: -webkit-text-fill-color | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/mdn-css_properties_-webkit-text-fill-color)

:::note warn
「-webkit-text-fill-color」についてMDNには「この機能は標準ではなく、標準化の予定もありません。公開されているウェブサイトには使用しないでください。」と強めの注意書きがあります。
:::

:::note info
- 該当ページ冒頭に登場する「すべてが新しいデザイン。」の部分です。
- 当プロパティが効かないブラウザにはcolorが適用されます。
- JavaScriptでスクロール値と連動してbackground-positionを変更することで変化させています。
- 「-webkit-text-fill-color」は非標準のプロパティであり、AutoPrefixerではベンダープレフィックスを付与できないため自分で書く必要があります。
:::
***

# 「TESLA」のフルページスワイプ
https://www.tesla.com/ja_jp

<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html,result" data-slug-hash="vYRqQVv" data-user="p_toro" 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/p_toro/pen/vYRqQVv">
  フルページスワイプ</a> by p_toro (<a href="https://codepen.io/p_toro">@p_toro</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```scss
scroll-snap-type: y mandatory;
```
[scroll-snap-type - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/scroll-snap-type)
[CSS property: scroll-snap-type | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/mdn-css_properties_scroll-snap-type)

**scroll-snap-type** → スナップ点が存在する場合に、スクロールコンテナーにどれだけ厳密にスナップ点を強制するかを、スナップする要素の親要素に設定します。「mandatory（義務的な、強制の）」ではスナップ点への吸着が強く、「proximity（近接）」では吸着が弱いです。

### scroll-snap関連
```scss
scroll-snap-align: start;
scroll-snap-stop: always;
```
[scroll-snap-align - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/scroll-snap-align)
[CSS property: scroll-snap-align | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/mdn-css_properties_scroll-snap-align)

[scroll-snap-stop - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/scroll-snap-stop)
[CSS property: scroll-snap-stop | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/mdn-css_properties_scroll-snap-stop)

**scroll-snap-align** → スクロールスナップ位置を指定します。「2つの値を指定すると、1番目がブロック、2番目がインラインとなる」らしいのですが、2つの値を指定すべきケースとその仕様・挙動を把握できなかったため詳細は割愛します。
**scroll-snap-stop** → スクロールコンテナーが可能なスナップ位置を「通り過ぎる」ことを許可するかどうかを定義します。

:::note warn
scroll-snap-alignはMDNによると「Safariは現在のところ、2つの値の構文を誤った順序で実装しており、最初の値がインラインで次の値がブロックになっています」とのことです。
:::
:::note info
- 表示領域の高さ指定が必須です。
- MDNに「現在スクロール中でなければ」という注釈がありますが、この影響のためかワンテンポ遅れて動作するような感覚があります。カスタムや微調整が必要な場合にはJSによる実装のほうがよいかもしれません。
- とはいえ「トレードオフ」で考えると、簡潔なコードで実装できるメリット（実装・メンテナンスコスト減）は魅力的です。
:::

***

# 「NIKE」の商品カルーセル
https://www.nike.com/jp/t/%E3%83%8A%E3%82%A4%E3%82%AD-%E3%82%A8%E3%82%A2-%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B9-1-07-%E3%83%A1%E3%83%B3%E3%82%BA%E3%82%B7%E3%83%A5%E3%83%BC%E3%82%BA-33DCrT/CW2288-111

<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html,result" data-slug-hash="YzampLZ" data-user="p_toro" 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/p_toro/pen/YzampLZ">
  カルーセル</a> by p_toro (<a href="https://codepen.io/p_toro">@p_toro</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
※デベロッパーツールで表示デバイスをスマホにしていただくと操作しやすいです。

```scss
scroll-snap-type: x mandatory;
```
※「TESLA」のフルページスワイプとの差は「指定している軸の違い」であり、説明が重複するのでこちらでは割愛します。

***
# 「airbnb」の追従メニュー
https://www.airbnb.jp/rooms/34113796?adults=1&category_tag=Tag%3A8225&children=0&infants=0&search_mode=flex_destinations_search&check_in=2023-08-12&check_out=2023-08-18&federated_search_id=c938e040-64fd-4c7b-8595-a0b92edf1782&source_impression_id=p3_1661852002_%2F5vCQq7YfJ5zneE7

<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html,result" data-slug-hash="rNdXGjR" data-user="p_toro" 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/p_toro/pen/rNdXGjR">
  スティッキーメニュー</a> by p_toro (<a href="https://codepen.io/p_toro">@p_toro</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```scss
position: sticky;
```
[position - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/position)
[CSS position:sticky | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/css-sticky)

:::note info
- スティッキーアイテム → sticky（粘着する）を適用した要素。ビューポートのポジションが定義したポジションと一致するとフロートします。
- スティッキーコンテナ → スティッキーアイテムをラップする親要素。スティッキーアイテムがフロートすることができる最大のエリアになります。
- スティッキーコンテナ内にスティッキーアイテムが唯一の要素だった場合、うまく機能しません。
:::

## まとめ
ご紹介したCSSはみなとても便利なものばかりで、JavaScriptを用いずともこのようなリッチな表現が実装できるということを再認識できて勉強になりました。
ただ、いずれも何も考えずコピペするのではなく、きちんと仕様を確認し各種プロパティの挙動を理解したうえで活用していくことが大切だと思いました。

## 参考サイト
- [【CSS】「これどうやる？」アップルやテスラのWebレイアウト再現テクニック集 - PhotoshopVIP](https://photoshopvip.net/136000)
- [CSSのスクロールスナップの便利な使い方、実装の注意点を徹底解説 | コリス](https://coliss.com/articles/build-websites/operation/css/usecase-of-css-scroll-snap.html)
- [CSS | scroll-snapでピタッと止まるスナップスクロールを実装する | ONE NOTES](https://1-notes.com/css-scroll-snap-type-y-mandatory/)
- [position: sticky;の仕組みや実際の使い方をやさしく解説 | コリス](https://coliss.com/articles/build-websites/operation/css/css-position-sticky-how-it-really-works.html)
- [CSSでAppleっぽいグラーデーションのテキストを作る](https://zenn.dev/catnose99/articles/ec601c8f2085ae)