【コピペOK】スワイプ型LPのコーディング実装ガイド

「スワイプ型LPを自分でコーディングしたいけど、どう実装すればいいかわからない…」

スワイプ型LPは、正しく実装すればCVR248%向上、読了率65%という効果を発揮します。しかし、実装を誤ると操作性が悪くなり、逆効果になることも。この記事では、コピペで使えるHTML/CSS/JavaScriptのコードサンプルとともに、スワイプ型LPの実装方法を解説します。

初心者でも実装できるよう、ステップバイステップで説明します。

実装前の準備

スワイプ型LPの実装に必要なものを確認しましょう。

必要なスキル

  • HTML:基本的な構造を書ける程度
  • CSS:flexbox、position、transitionの理解
  • JavaScript:イベントハンドリングの基礎

用意するもの

  • スライド画像:390 x 844px推奨(8〜12枚)
  • コードエディタ:VSCode等
  • ローカルサーバー:Live Server等(動作確認用)

基本構造(HTML)

まずは、スワイプ型LPの基本的なHTML構造を作成します。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>スワイプ型LP</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="lp-container">
        <!-- プログレスインジケーター -->
        <div class="progress-bar">
            <div class="progress-fill"></div>
        </div>

        <!-- スライドコンテナ -->
        <div class="slides-wrapper">
            <div class="slide active">
                <img src="slide1.jpg" alt="スライド1">
            </div>
            <div class="slide">
                <img src="slide2.jpg" alt="スライド2">
            </div>
            <div class="slide">
                <img src="slide3.jpg" alt="スライド3">
            </div>
            <!-- 必要な枚数だけ追加 -->
        </div>

        <!-- 固定CTA -->
        <div class="fixed-cta">
            <a href="#" class="cta-button">今すぐ申し込む</a>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

HTML構造のポイント

  • viewport設定user-scalable=noでピンチズームを無効化
  • progress-bar:上部に進捗バーを配置
  • slides-wrapper:全スライドを包含するコンテナ
  • fixed-cta:画面下部に固定するCTAボタン

スタイリング(CSS)

次に、スワイプ操作を実現するためのCSSを記述します。

CSS
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    height: 100%;
    overflow: hidden;
    touch-action: none;
}

#lp-container {
    position: relative;
    width: 100%;
    height: 100%;
    max-width: 430px;
    margin: 0 auto;
    background: #000;
}

/* プログレスバー */
.progress-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: rgba(255,255,255,0.3);
    z-index: 100;
}

.progress-fill {
    height: 100%;
    background: #ff6b6b;
    width: 0%;
    transition: width 0.3s ease;
}

/* スライドコンテナ */
.slides-wrapper {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.slide {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    transform: translateY(100%);
    transition: all 0.4s ease-out;
}

.slide.active {
    opacity: 1;
    transform: translateY(0);
}

.slide.prev {
    opacity: 0;
    transform: translateY(-30%);
}

.slide img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* 固定CTA */
.fixed-cta {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 16px;
    padding-bottom: calc(16px + env(safe-area-inset-bottom));
    background: linear-gradient(transparent, rgba(0,0,0,0.8));
    z-index: 50;
}

.cta-button {
    display: block;
    width: 100%;
    max-width: 400px;
    margin: 0 auto;
    padding: 18px 32px;
    background: #ff6b6b;
    color: #fff;
    text-align: center;
    text-decoration: none;
    font-size: 18px;
    font-weight: bold;
    border-radius: 12px;
    box-shadow: 0 4px 12px rgba(255,107,107,0.4);
}

/* PC表示時の調整 */
@media (min-width: 430px) {
    #lp-container {
        height: 100vh;
        box-shadow: 0 0 30px rgba(0,0,0,0.3);
    }
}

CSSのポイント

プロパティ 目的
touch-action: none ブラウザのデフォルトスワイプを無効化
overflow: hidden スクロールを防止
transform: translateY スライドアニメーション
env(safe-area-inset-bottom) iPhoneのセーフエリア対応

スワイプ処理(JavaScript)

スワイプ操作を検出し、スライドを切り替えるJavaScriptを実装します。

JavaScript
class SwipeLP {
    constructor() {
        this.slides = document.querySelectorAll('.slide');
        this.progressFill = document.querySelector('.progress-fill');
        this.currentIndex = 0;
        this.totalSlides = this.slides.length;
        this.startY = 0;
        this.endY = 0;
        this.isAnimating = false;

        this.init();
    }

    init() {
        // タッチイベント
        document.addEventListener('touchstart', (e) => this.handleTouchStart(e));
        document.addEventListener('touchend', (e) => this.handleTouchEnd(e));

        // マウスイベント(PC対応)
        document.addEventListener('mousedown', (e) => this.handleMouseDown(e));
        document.addEventListener('mouseup', (e) => this.handleMouseUp(e));

        // ホイールイベント(PC対応)
        document.addEventListener('wheel', (e) => this.handleWheel(e));

        // 初期表示
        this.updateProgress();
    }

    handleTouchStart(e) {
        this.startY = e.touches[0].clientY;
    }

    handleTouchEnd(e) {
        this.endY = e.changedTouches[0].clientY;
        this.handleSwipe();
    }

    handleMouseDown(e) {
        this.startY = e.clientY;
    }

    handleMouseUp(e) {
        this.endY = e.clientY;
        this.handleSwipe();
    }

    handleWheel(e) {
        if (this.isAnimating) return;

        if (e.deltaY > 0) {
            this.nextSlide();
        } else {
            this.prevSlide();
        }
    }

    handleSwipe() {
        if (this.isAnimating) return;

        const threshold = 50; // スワイプ判定の閾値
        const diff = this.startY - this.endY;

        if (diff > threshold) {
            this.nextSlide();
        } else if (diff < -threshold) {
            this.prevSlide();
        }
    }

    nextSlide() {
        if (this.currentIndex >= this.totalSlides - 1) return;

        this.isAnimating = true;
        this.slides[this.currentIndex].classList.remove('active');
        this.slides[this.currentIndex].classList.add('prev');
        this.currentIndex++;
        this.slides[this.currentIndex].classList.add('active');

        this.updateProgress();

        setTimeout(() => {
            this.slides[this.currentIndex - 1].classList.remove('prev');
            this.isAnimating = false;
        }, 400);
    }

    prevSlide() {
        if (this.currentIndex <= 0) return;

        this.isAnimating = true;
        this.slides[this.currentIndex].classList.remove('active');
        this.currentIndex--;
        this.slides[this.currentIndex].classList.remove('prev');
        this.slides[this.currentIndex].classList.add('active');

        this.updateProgress();

        setTimeout(() => {
            this.isAnimating = false;
        }, 400);
    }

    updateProgress() {
        const progress = ((this.currentIndex + 1) / this.totalSlides) * 100;
        this.progressFill.style.width = progress + '%';
    }
}

// 初期化
document.addEventListener('DOMContentLoaded', () => {
    new SwipeLP();
});

JavaScriptのポイント

  • threshold:50px以上のスワイプで切り替え判定
  • isAnimating:連続スワイプ防止フラグ
  • wheel対応:PCでのマウスホイール操作
  • updateProgress:進捗バーの更新

応用:オーバーレイテキストの追加

画像上にテキストを重ねる実装方法です。

HTML(スライド部分)
<div class="slide">
    <img src="slide1.jpg" alt="スライド1">
    <div class="overlay-text">
        <h2 class="headline">CVR248%UP</h2>
        <p class="subtext">スワイプ型LPで成果を出す</p>
    </div>
</div>
CSS(オーバーレイ用)
.overlay-text {
    position: absolute;
    bottom: 120px;
    left: 20px;
    right: 20px;
    color: #fff;
    text-shadow: 0 2px 8px rgba(0,0,0,0.5);
}

.headline {
    font-size: 32px;
    font-weight: 900;
    margin-bottom: 8px;
}

.subtext {
    font-size: 16px;
}

応用:計測タグの埋め込み

スライドごとの閲覧データを取得するための実装です。

JavaScript(計測用)
// Google Analytics 4 対応の計測
function trackSlideView(slideIndex) {
    if (typeof gtag !== 'undefined') {
        gtag('event', 'slide_view', {
            'slide_number': slideIndex + 1,
            'slide_total': this.totalSlides
        });
    }
}

// nextSlide()内で呼び出し
nextSlide() {
    // ... 既存のコード ...
    trackSlideView(this.currentIndex);
}

計測のポイント

スライドごとの離脱率を計測することで、「何枚目で離脱が多いか」を特定できます。これがスワイプ型LPの改善しやすさにつながり、離脱率50%減に貢献します。

よくあるエラーと解決法

エラー/問題 原因 解決法
スワイプが効かない touch-actionの設定漏れ body に touch-action: none を追加
画面が揺れる overflow設定の問題 html, body に overflow: hidden を追加
iPhoneで下にスペースが出る セーフエリア未対応 env(safe-area-inset-bottom) を使用
連続スワイプでバグる アニメーション中の処理 isAnimatingフラグで制御

実践チェックリスト

実装完了後のチェックリストです。

  • スマホ実機でスワイプ操作が動作する
  • PCでマウスホイール操作が動作する
  • プログレスバーが正しく更新される
  • CTAボタンが常に表示されている
  • セーフエリアが確保されている
  • 画像が画面に収まっている(はみ出していない)
  • アニメーションがスムーズに動く
  • 計測タグが正しく発火している

もっと簡単に作りたい方へ

コーディングに自信がない方や、もっと手軽にスワイプ型LPを作成したい方には、ノーコードツールの活用がおすすめです。

当サイトのスワイプ型LP作成ツールなら、画像をアップロードするだけで簡単にスワイプ型LPが作成できます。HTML/CSS/JavaScriptの知識は不要です。

まとめ

スワイプ型LPの実装は、HTML/CSS/JavaScriptの基礎知識があれば可能です。この記事で紹介したコードをベースに、自社の商材に合わせてカスタマイズしてください。

正しく実装されたスワイプ型LPは、CVR248%向上、離脱率50%減、読了率65%といった効果をもたらします。計測タグも忘れずに埋め込み、継続的な改善を行いましょう。

この記事のポイント

  • HTML:シンプルなdiv構造でスライドを配置
  • CSS:touch-action、overflow、transformがキー
  • JS:タッチイベントでスワイプを検出
  • セーフエリア対応を忘れずに
  • 計測タグでスライドごとの分析が可能

コーディング不要で作成

画像をアップロードするだけでスワイプ型LPが完成

ツールを開く