ライブデモ Live Demo

下にスクロールすると、要素がふわっと表示されます。

Scroll down to see elements fade in.

Spacer Area

Reward 1

Fade in content as it enters viewport

Spacer Area

Reward 2

Smooth translation and opacity change

Spacer Area

Reward 3

Keep scrolling...

0.8s
40px

AI向け説明 AI Description

`M-012` は Intersection Observer API を使用して、要素がビューポート(または親コンテナ)に入ったことを検知し、クラスを付与して CSS トランジションを発火させます。パフォーマンスが高く、スクロールイベントリスナーよりも推奨される手法です。

`M-012` utilizes the Intersection Observer API to detect when elements enter the viewport (or a root container), toggling a class to trigger CSS transitions. This approach is more performant than scroll event listeners.

調整可能パラメータ Adjustable Parameters

実装 Implementation

HTML + CSS + JS

<div class="reveal-item">Content</div>

<style>
.reveal-item {
  opacity: 0;
  transform: translateY(var(--reveal-distance, 40px));
  transition: all var(--reveal-duration, 0.8s) cubic-bezier(0.5, 0, 0, 1);
}
.reveal-item.visible {
  opacity: 1;
  transform: translateY(0);
}
</style>

<!-- Parameters -->
<div class="control-row">
  <label for="dur_control">Duration:</label>
  <input type="range" id="dur_control" min="0.1" max="2" step="0.1" value="0.8">
  <span id="dur_value">0.8s</span>
</div>
<div class="control-row">
  <label for="dist_control">Distance:</label>
  <input type="range" id="dist_control" min="0" max="100" step="5" value="40">
  <span id="dist_value">40px</span>
</div>

<!-- Controls Script -->
<script>
  window.addEventListener('vibeui:ready', () => {
    const container = document.getElementById('scroll_ctx');
    
    // Duration
    const durInput = document.getElementById('dur_control');
    const durOutput = document.getElementById('dur_value');
    if(durInput) {
      durInput.addEventListener('input', (e) => {
        const val = e.target.value;
        durOutput.textContent = val + 's';
        container.style.setProperty('--reveal-duration', val + 's');
      });
    }

    // Distance
    const distInput = document.getElementById('dist_control');
    const distOutput = document.getElementById('dist_value');
    if(distInput) {
      distInput.addEventListener('input', (e) => {
        const val = e.target.value;
        distOutput.textContent = val + 'px';
        container.style.setProperty('--reveal-distance', val + 'px');
      });
    }
  });
</script>

<script>
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
    }
  });
}, { threshold: 0.1 }); // rootMargin if needed

document.querySelectorAll('.reveal-item').forEach(el => observer.observe(el));
</script>

React (JSX + CSS)

// react/M-012.jsx
import { useEffect, useRef } from 'react';
import './M-012.css';

export default function ScrollReveal({ children }) {
  const ref = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        ref.current.classList.add('visible');
      }
    }, { threshold: 0.1 });
    
    if (ref.current) observer.observe(ref.current);
    return () => observer.disconnect();
  }, []);

  return <div className="reveal-item" ref={ref}>{children}</div>;
}

AIへの指示テンプレート AI Prompt Template

以下のテンプレートをコピーしてAIアシスタントに貼り付けると、このパターンの実装を依頼できます。 Copy the template below and paste it into your AI assistant to request an implementation of this pattern.