シンプルで崩れにくいビフォーアフター比較スライダーの作り方(HTML/CSS/JS)

当サイトには広告が含まれています。

たまに見かけるビフォーアフター的なものです。

画像が2枚あって、真ん中のアイコンを横にスライドさせると、写真の表示される範囲が変わるというものを作ります。

目次

実装サンプル

触ってみてください。

After Image
AFTER
Before Image
BEFORE

他の方のブログを参考にしたり、JSライブラリを使おうとしたのですが、どれもうまくいかず、結果chatGPTに書いてもらいました。

今はなんでもAIで解決できる感じなのですが、一応ブログのネタとして、ここにコードを残しておきます。

スマホでもちゃんと動きます。

HTML

画像のパスは変更してください。

HTML
<section class="image-comparison-slider">
    <div class="image-container background-img">
        <img src="https://picsum.photos/id/10/800/500" alt="After Image">
        <div class="image-label label-after">AFTER</div>
    </div>
    
    <div class="image-container foreground-img">
        <img src="https://picsum.photos/id/11/800/500" alt="Before Image">
        <div class="image-label label-before">BEFORE</div>
    </div>

    <div class="slider-handle">
        <div class="slider-icon">
            <span></span><span></span>
        </div>
    </div>
</section>

CSS

CSS
.image-comparison-slider {
    position: relative;
    width: 100%;
    height: 500px;
    overflow: hidden;
    user-select: none;
    margin-bottom: 1.5rem;
    touch-action: pan-y;
}

/* 画像コンテナの共通設定 */
.image-comparison-slider .image-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/* 画像伸縮を強制上書き */
.image-comparison-slider .image-container img {
    display: block !important;
    width:  100% !important;
    min-width: 1100px !important;
    max-width: 1100px !important;
    height: 500px !important;
    object-fit: cover !important;
}

/* 前面画像(最初は50%の幅で表示) */
.image-comparison-slider .foreground-img {
    width: 50%;
    overflow: hidden;
    z-index: 2;
}

/* 背景画像 */
.image-comparison-slider .background-img {
    z-index: 1;
}

/* 中央のスライダーバー(縦線) */
.image-comparison-slider .slider-handle {
    position: absolute;
    top: 0;
    left: 50%;
    width: 4px;
    height: 100%;
    background-color: #ffffff;
    cursor: ew-resize;
    z-index: 4;
    transform: translateX(-50%);
    touch-action: pan-y;
}

/* スライダー中央の丸いアイコン */
.image-comparison-slider .slider-icon {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 40px;
    height: 40px;
    background-color: #ffffff;
    border-radius: 50%;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 6px;
    box-sizing: border-box;
    color: #555555;
    font-size: 12px;
    font-weight: bold;
}

/* Before/After ラベルのスタイル */
.image-comparison-slider .image-label {
    position: absolute;
    top: 15px;
    padding: 6px 12px;
    background-color: rgba(0, 0, 0, 0.6);
    color: #ffffff;
    font-size: 14px;
    font-weight: bold;
    letter-spacing: 1px;
    border-radius: 4px;
    pointer-events: none; /* ドラッグ操作を邪魔しない */
    z-index: 3;
}

.image-comparison-slider .label-before { left: 15px; }
.image-comparison-slider .label-after { right: 15px; }


@media screen and (max-width: 650px) {
    .image-comparison-slider {
        height: 300px;
    }

    /* 中の画像を「横幅は画面いっぱい(100vw)、高さは350px」に固定 */
    .image-comparison-slider .image-container img {
        width: 100vw !important;
        min-width: 100vw !important;
        max-width: 100vw !important;
        height: 300px !important;
    }
}

Java script

jQueryは使いません。

JavaScript
(function() {
    // ページの読み込み完了を待ってから実行
    window.addEventListener('DOMContentLoaded', () => {
        const currentSection = document.querySelector('.image-comparison-slider');
        if (!currentSection) return; // スライダーが存在しないページでは処理をスキップ

        const container = currentSection;
        const foregroundImg = currentSection.querySelector('.foreground-img');
        const handle = currentSection.querySelector('.slider-handle');

        let isDragging = false;

        // スライダーを動かすメイン関数
        function moveSlider(x) {
            const rect = container.getBoundingClientRect();
            let position = x - rect.left;

            // コンテナの範囲内に制限
            if (position < 0) position = 0;
            if (position > rect.width) position = rect.width;

            const percentage = (position / rect.width) * 100;

            // 表示の更新
            foregroundImg.style.width = `${percentage}%`;
            handle.style.left = `${percentage}%`;
        }

        /* マウス操作 */
        handle.addEventListener('mousedown', () => { isDragging = true; });
        window.addEventListener('mouseup', () => { isDragging = false; });
        window.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            moveSlider(e.clientX);
        });

        /* タッチ操作(スマホ対応) */
        handle.addEventListener('touchstart', () => { isDragging = true; });
        window.addEventListener('touchend', () => { isDragging = false; });
        window.addEventListener('touchmove', (e) => {
            if (!isDragging) return;
            moveSlider(e.touches[0].clientX);
        });
    });
})();

デザイン作るの難しい〜!と感じたら

デザイン・ホームページで

お困りのことがありましたら、
私たちクートスラボにご依頼ください!
実績多数の女性クリエイターチームが、

どんなお悩みも解決します。

\ 見積もり・ご依頼はこちら! /

シェアお願いします!
  • URLをコピーしました!
目次