【CSS/Javascript】スクロールに応じたマスクサイズや要素サイズの変更方法

【CSS/Javascript】スクロールに応じたマスクサイズや要素サイズの変更方法

Webデザインやインタラクションの設計において、スクロールに応じてマスクや要素のサイズを動的に変化させる手法は、視覚的なインパクトを高めるだけでなく、ユーザーエクスペリエンスの向上にも貢献します。本記事では、スクロールに応じたサイズ変更の実装方法を紹介します。

1. CSSとJavaScriptを使った基本的な実装

HTMLの基本構造

<div class="mask_area">
<div class="mask"></div>
<div class="scaling-element"></div>
</div>

CSS

.mask_area {
margin: 0;
height: 300px;
background: linear-gradient(to bottom, #fff, #ccc);
overflow: hidden;
}
.mask {
width: 100%;
height: 300px;
overflow: hidden;
position: relative;
background: #333;
transition: height 0.3s ease;
}
.scaling-element {
width: 100px;
height: 100px;
background: red;
margin: 50px auto;
transform: scale(1);
transition: transform 0.3s ease;
}
</style>

Javascript

<script>
        window.addEventListener("scroll", function() {
            const scrollY = window.scrollY;
            const mask = document.querySelector(".mask");
            const newHeight = Math.max(100, 300 - scrollY * 0.5); // 最小サイズを100pxに制限
            mask.style.height = `${newHeight}px`;

            const element = document.querySelector(".scaling-element");
            const scale = Math.max(0.5, 1 - scrollY * 0.001); // 最小スケールを0.5に制限
            element.style.transform = `scale(${scale})`;
        });
    </script>

2. Intersection Observerを活用したパフォーマンス向上

Intersection Observerとは?

Intersection Observer は、指定した要素がビューポート内に入ったかどうかを検知するAPIです。従来の scroll イベントを利用した方法と比べて、パフォーマンスの向上や不要なイベント処理の削減が可能になります。

メリット:

  • スクロールイベントの連続処理を減らせるため、パフォーマンスが向上
  • 画面内に入った要素のみ処理できる
  • ビューポート外の要素に対して不要な計算を回避できる

JavaScriptの実装

const target = document.querySelector(".mask");
const observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const scrollY = window.scrollY;
      const newHeight = Math.max(100, 300 - scrollY * 0.5);
      entry.target.style.height = `${newHeight}px`;
    }
  });
});

observer.observe(target);

スクロール要素とマスクサイズの設定

1. window.scrollY を使用したスクロール量の取得

const scrollY = window.scrollY;
  • window.scrollY を使って現在のスクロール位置を取得しています。

2. マスクサイズの変更

const newHeight = Math.max(100, 300 - scrollY * 0.5); // 最小サイズを100pxに制限
mask.style.height = `${newHeight}px`;
  • scrollY * 0.5 でスクロール量に応じて mask の高さを減少させています。
  • Math.max(100, ...) で最小値を100pxに制限。

3. 要素のスケール変更

const scale = Math.max(0.5, 1 - scrollY * 0.001); // 最小スケールを0.5に制限
element.style.transform = `scale(${scale})`;
  • scrollY * 0.001 によって scale() を徐々に小さくしています。
  • Math.max(0.5, ...) で最小値を 0.5 に制限。

4. Intersection Observer による制御

const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const scrollY = window.scrollY;
const newHeight = Math.max(100, 300 - scrollY * 0.5);
entry.target.style.height = `${newHeight}px`;
}
});
});
observer.observe(target);
  • .mask 要素が画面に表示されているときのみ高さを変更することで、パフォーマンスを向上。

このように、スクロールの値 (scrollY) を取得し、計算を適用することでサイズやスケールを動的に変更しています。調整したい場合は、scrollY にかける係数 (0.50.001) を変えると動きが変わります!

まとめ

スクロールに応じたマスクサイズや要素サイズの変更は、インタラクティブなデザインにおいて非常に有効なテクニックです。CSSの transform を活用したスケール変更や、 Intersection Observer を使った最適化を取り入れることで、スムーズなアニメーションを実現しつつ、パフォーマンスを維持することができます。ぜひ、プロジェクトに活用してみてください!