Bloggerに関するカスタマイズ・テンプレート・TIPSを紹介しています。

2026/02/28

Bloggerデザイン : イメージ比較スライダー

1. デザインのタイプ

【インタラクティブ・イメージ比較スライダー】
2枚の画像を重ね、ユーザーが境界線を左右にドラッグすることで、変化(Before/After)を直感的に比較できるデザイン。リアルタイムな視覚フィードバックにより、加工効果やビフォーアフターの差異を劇的に演出します。

加工前の写真(左側の写真)
加工後の写真(右側の写真)

2. デザインの特徴

  • リアルタイム・マスキング処理
    左側の画像を動的にクリッピングすることで、左右の画像の解像度や拡大率を完全に一致させたまま比較が可能。
  • ハイブリッド・レスポンシブ
    PCでは境界線のドラッグ、スマホでは画像全体のタッチ操作に対応し、デバイスを問わずスムーズに動作。
  • 視覚的ガイド・UI
    境界線中央に配置されたダブルアローアイコンにより、直感的な操作感と高い視認性を実現。

3. 紹介コード

HTML・CSS JavaScript


<div class="comparison-block" id="comparison-slider">
  <span class="comparison-arrow"></span>
  <div class="comparison-before-img">
    <img src="画像URL" alt="加工前の写真(左側の写真)">
  </div>
  <div class="comparison-after-img">
    <img src="画像URL" alt="加工後の写真(右側の写真)">
  </div>
</div>

<style>
/* --- スライダーのスタイル --- */
.comparison-block {
    width: 100%;
    max-width: 640px;
    position: relative;
    margin: 20px auto;
    overflow: hidden;
    user-select: none;
    -webkit-user-select: none;
    line-height: 0;
}

.comparison-block::selection, .comparison-block *::selection { background-color: transparent; }
.comparison-block::-moz-selection, .comparison-block *::-moz-selection { background-color: transparent; }

.comparison-before-img {
    position: absolute;
    top: 0;
    left: 0;
    width: 50%;
    height: 100%;
    overflow: hidden;
    z-index: 5;
}

.comparison-before-img img {
    height: 100% !important;
    width: auto !important;
    display: block;
    max-width: none !important;
    object-fit: cover;
    object-position: left center;
}

.comparison-after-img {
    position: relative;
    z-index: 1;
}

.comparison-after-img img {
    width: 100%;
    height: auto;
    display: block;
}

.comparison-arrow {
    background-color: #fff;
    position: absolute;
    z-index: 10;
    top: 0;
    width: 2px;
    height: 100%;
    left: 50%;
    cursor: ew-resize;
}

.comparison-arrow:after {
    content: '';
    display: block;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background-color: #fff;
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="%23333" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="11 17 6 12 11 7"/><polyline points="13 17 18 12 13 7"/></svg>');
    background-repeat: no-repeat;
    background-position: center;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}
</style>
  

<script>
// <![CDATA[
(function() {
  const blockElements = document.getElementsByClassName('comparison-block');
  const arrows = document.getElementsByClassName('comparison-arrow');
  const beforeDivs = document.getElementsByClassName('comparison-before-img');
  
  let device = (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|Windows Phone)/)) ? 'smt' : 'pc';
  let startEvent = (device === 'smt') ? 'touchstart' : 'mousedown';
  let moveEvent = (device === 'smt') ? 'touchmove' : 'mousemove';
  let endEvent = (device === 'smt') ? 'touchend' : 'mouseup';

  let isDragging = false;
  let activeSlider = null;

  function initLayout() {
    for (let i = 0; i < blockElements.length; i++) {
      let width = blockElements[i].clientWidth;
      let beforeImg = beforeDivs[i].querySelector('img');
      if (beforeImg) {
        beforeImg.style.width = width + 'px';
      }
      beforeDivs[i].style.width = (width / 2) + 'px';
      arrows[i].style.left = (width / 2) + 'px';
    }
  }

  function onStart(e) {
    isDragging = true;
    activeSlider = this.closest('.comparison-block');
    if (device === 'pc') {
        window.addEventListener(moveEvent, onMove);
    } else {
        activeSlider.addEventListener(moveEvent, onMove, { passive: false });
    }
  }

  function onMove(e) {
    if (!isDragging || !activeSlider) return;
    
    let event = (device === 'smt') ? e.changedTouches[0] : e;
    let rect = activeSlider.getBoundingClientRect();
    let arrow = activeSlider.querySelector('.comparison-arrow');
    let beforeDiv = activeSlider.querySelector('.comparison-before-img');
    
    let x = event.pageX - (rect.left + window.pageXOffset);
    let maxX = activeSlider.clientWidth;

    if (x < 0) x = 0;
    if (x > maxX) x = maxX;

    arrow.style.left = x + 'px';
    beforeDiv.style.width = x + 'px';
    
    if (device === 'smt') e.preventDefault();
  }

  function onEnd() {
    isDragging = false;
    if (activeSlider && device === 'smt') {
        activeSlider.removeEventListener(moveEvent, onMove);
    }
    window.removeEventListener(moveEvent, onMove);
    activeSlider = null;
  }

  window.addEventListener('load', initLayout);
  window.addEventListener('resize', initLayout);

  for (let i = 0; i < blockElements.length; i++) {
    let target = (device === 'smt') ? blockElements[i] : arrows[i];
    target.addEventListener(startEvent, onStart);
  }
  
  window.addEventListener(endEvent, onEnd);
})();
// ]]>
</script>
  
まつゆう
アラフォーゲーマーがいろんなゲームを楽しみながらプレイしています。YouTube・Twitch・Mixerで配信中!! 東京パフォーマンスドールの狂信者。 好きすぎてドメインを取得してファンサイトを運営中。

0 comments:

コメントを投稿