← 動的パーツギャラリーへ戻る

パーツ番号 08-08-08 ・ JavaScript使用

横スワイプ切替タブコンテンツ

タブタップに加えて、コンテンツ本体を左右にドラッグしてもパネルが切り替わります。WordPressの商品スペック・レビュー切替セクションに便利です。

mobileclickdragjs

プレビュー

ソースコード

HTML

<div class="d08-08-08-wrap">
          <div class="d08-08-08-tabs">
            <button class="d08-08-08-tab is-on" type="button">概要</button>
            <button class="d08-08-08-tab" type="button">仕様</button>
            <button class="d08-08-08-tab" type="button">レビュー</button>
          </div>
          <div class="d08-08-08-track">
            <div class="d08-08-08-panel">シンプルで軽量なワイヤレスイヤホン。連続再生8時間。</div>
            <div class="d08-08-08-panel">Bluetooth5.3/IPX4防水/重量4.5g</div>
            <div class="d08-08-08-panel">★4.6(238件)「装着感が良い」との声多数</div>
          </div>
          <div class="d08-08-08-indicator"><span class="is-on"></span><span></span><span></span></div>
        </div>

CSS

.d08-08-08-wrap{width:100%;max-width:280px}
        .d08-08-08-tabs{display:flex;gap:6px;margin-bottom:10px}
        .d08-08-08-tab{flex:1;background:#f1f2f6;border:none;border-radius:8px;padding:8px 4px;font-size:11.5px;font-weight:700;color:#6b7280;cursor:pointer;transition:background .2s,color .2s}
        .d08-08-08-tab.is-on{background:#6a5cff;color:#fff}
        .d08-08-08-track{display:flex;width:100%;overflow:hidden;touch-action:pan-y;cursor:grab}
        .d08-08-08-panel{flex:0 0 100%;font-size:12px;color:#555;line-height:1.7;min-height:80px;padding:4px 2px}
        .d08-08-08-indicator{display:flex;justify-content:center;gap:6px;margin-top:10px}
        .d08-08-08-indicator span{width:7px;height:7px;border-radius:50%;background:#d8dae2;transition:background .2s}
        .d08-08-08-indicator span.is-on{background:#6a5cff}

JavaScript

(function(){
        var root=document.querySelector('#item-08-08-08 .d08-08-08');
        var track=root&&root.querySelector('.d08-08-08-track');
        var tabs=root?root.querySelectorAll('.d08-08-08-tab'):[];
        var dots=root?root.querySelectorAll('.d08-08-08-indicator span'):[];
        if(!track)return;
        var count=track.querySelectorAll('.d08-08-08-panel').length;
        var index=0,startX=0,curX=0,dragging=false;
        function getX(e){return e.touches&&e.touches.length?e.touches[0].clientX:e.clientX;}
        function goTo(i){
          index=Math.max(0,Math.min(count-1,i));
          track.style.transition='transform .3s cubic-bezier(.2,.8,.2,1)';
          track.style.transform='translateX(-'+(index*100)+'%)';
          tabs.forEach(function(t,i2){t.classList.toggle('is-on',i2===index);});
          dots.forEach(function(d,i2){d.classList.toggle('is-on',i2===index);});
        }
        function render(anim){
          track.style.transition=anim?'transform .3s cubic-bezier(.2,.8,.2,1)':'none';
          track.style.transform='translateX(calc(-'+(index*100)+'% + '+curX+'px))';
        }
        function onDown(e){
          dragging=true;curX=0;startX=getX(e);
          document.addEventListener('mousemove',onMove);
          document.addEventListener('mouseup',onUp);
        }
        function onMove(e){
          if(!dragging)return;
          if(e.cancelable)e.preventDefault();
          curX=getX(e)-startX;render(false);
        }
        function onUp(){
          if(!dragging)return;
          dragging=false;
          var next=index;
          if(curX<-40&&index<count-1)next=index+1;
          else if(curX>40&&index>0)next=index-1;
          curX=0;
          goTo(next);
          document.removeEventListener('mousemove',onMove);
          document.removeEventListener('mouseup',onUp);
        }
        track.addEventListener('mousedown',onDown);
        track.addEventListener('touchstart',onDown,{passive:true});
        track.addEventListener('touchmove',onMove,{passive:false});
        track.addEventListener('touchend',onUp);
        tabs.forEach(function(t,i){t.addEventListener('click',function(){goTo(i);});});
        goTo(0);
      })();

クラス名 .d08-08-08 は本ライブラリ内での識別用です。複数のパーツを同じページで使う場合は、重複しないよう名前を変更してください。