arTab

Chromeライクな角丸のタブ機能。

CSSに関しては一部CSSライブラリを採用しているので併用してください。

  • DEMO
  • タブ1
  • タブ2
  • タブ3
表示1
表示2
表示3

使い方

*-li-*に+-.act-+のクラス追加で初期表示可能。

タブボタンは{overflow-x: auto;}しているので超過分はスクロール表示になります。
PCの時はカッコ悪いので注意。その内直す予定です。

スマホの時は表示部分をスワイプでも切替可能です。

見た目的に残しておこうと思ったのと、シンプルなマークアップで使いやすいのでJSは作り込んでいません。
なので通常のTabのようにネストや色々なサーチはできません。
恐らく複数設置も不可かも。

背景色のは初期から入れているので変更したい場合はCSSを書き換えてください。

  • HTML
  • CSS
  • Script
.arTabMod {
      padding: 24px;
      background: #dde3e9;
    }
    .arTabMod-list {
      padding: 0 16px;
      display: flex;
      gap: 6px;
      overflow-x: auto;
      overflow-y: hidden;
    }
    .arTabMod-btn {
      padding: 4px 0;
      font-size: var(--typo-min);
      align-self: flex-end;
    }
    .arTabMod-btn-in {
      min-width: 80px;
      padding: 2px 8px;
      position: relative;
      box-sizing: border-box;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .arTabMod-btn.act {
      border-radius: 6px 6px 0 0;
      background: var(--bg-paper);
      position: relative;
      z-index: 1;
    }
    .arTabMod-btn.act::before,
    .arTabMod-btn.act::after {
      content: '';
      width: 12px;
      height: 6px;
      border-radius: 0 0 6px 6px;
      background: #dde3e9;
      display: block;
      position: absolute;
      bottom: 0;
      z-index: 3;
    }
    .arTabMod-btn.act::before {left: -12px;}
    .arTabMod-btn.act::after {right: -12px;}
    .arTabMod-btn.act .arTabMod-btn-in::before,
    .arTabMod-btn.act .arTabMod-btn-in::after {
      content: '';
      width: 8px;
      height: 6px;
      background: var(--bg-paper);
      display: block;
      position: absolute;
      bottom: -6px;
      z-index: 2;
    }
    .arTabMod-btn.act .arTabMod-btn-in::before {left: -8px;}
    .arTabMod-btn.act .arTabMod-btn-in::after {right: -8px;}
    .arTabMod-btn:not(.act) .arTabMod-btn-in {
      width: 100%;
      border-radius: 6px;
      top: -2px;
      transition: .2s;
      cursor: pointer;
    }
    .arTabMod-btn:not(.act) .arTabMod-btn-in:hover {
      background: rgba(0,0,0,0.08);
      z-index: 2;
    }
    
    .arTabMod-sec {
      padding: 16px;
      border-radius: 6px;
      background: var(--bg-paper);
      display: flex;
      gap: 16px;
      overflow: hidden;
    }
    .arTabMod-item {
      min-width: 100%;
      transition: .2s;
    }
    @media screen and (max-width: 768px) {
      .arTabMod {padding: 24px 16px;}
    }
var isTouch = ('ontouchstart' in window);
    $('.arTabMod').each(function(){
      let $list = $('.arTabMod-list',this);
      let $btn = $list.children();
      let $sec = $('.arTabMod-sec',this);
      let $itm = $sec.children();
    
      $btn.addClass('arTabMod-btn').wrapInner('
'); $itm.addClass('arTabMod-item'); $sec.show(); //初期表示 if($list.children('.act')[0]){ let i = $list.children('.arTabMod-btn.act').index(); let mgn = 0; if(i != 0){mgn = 16*i} $itm.css('transform','translateX(calc(-'+ i +'00% - '+mgn+'px))'); $sec.height($('.arTabMod-item').eq(i).children().height()); } else { let $t = $btn.eq(0); $t.addClass('act'); } }); $bd.on('click','.arTabMod-btn-in',function(){ if($(this).hasClass('act')){return false;} let $btn = $(this).parent(); let $Mod = $(this).parents('.arTabMod'); let $sec = $Mod.find('.arTabMod-sec'); let $itm = $Mod.find('.arTabMod-item'); let i = $btn.index(); let mgn = 0; if(i != 0){mgn = 16*i} $btn.addClass('act').siblings().removeClass('act'); $itm.css('transform','translateX(calc(-'+ i +'00% - '+mgn+'px))'); $sec.height($itm.eq(i).children().height()); }); $('.arTabMod-sec').bind({ 'touchstart': function(e){ this.pageX = (isTouch ? event.changedTouches[0].pageX : e.pageX); this.pageY = (isTouch ? event.changedTouches[0].pageY : e.pageY); this.touchedTabSec = true; this.touched = false; }, 'touchmove': function(e){ if(!this.touchedTabSec){return;} this.pageXm = (isTouch ? event.changedTouches[0].pageX : e.pageX); this.pageYm = (isTouch ? event.changedTouches[0].pageY : e.pageY); if(this.pageXm != 0){ let i = $('.arTabMod-btn.act').index(); if(this.pageXm - this.pageX > 0 && i == 0 || this.pageXm - this.pageX < 0 && i + 1 == $('.arTabMod-btn').length){ this.touchedTabSec = false; return; } if(i == 0){var X = 0;} else {var X = -(i * 100);} let yc = this.pageXm - this.pageX + 1 + X; $('.arTabMod-item').css({ 'transform':'translateX(' + yc + '%)', 'transition':'0.1s' }); nowTouch = true; } }, 'touchend': function(e){ if(!this.touchedTabSec){return;} this.touchedTabSec = false; this.left = this.pageX - (isTouch ? event.changedTouches[0].pageX : e.pageX); this.top = this.pageY - (isTouch ? event.changedTouches[0].pageY : e.pageY); if(this.top == 0 && this.left == 0){return;} let $btn = $('.arTabMod-btn'); let $act = $('.arTabMod-btn.act'); let $itm = $('.arTabMod-item'); let i = $act.index(); let mgn = 16; let Xm = 100; if(this.left > 24){// NEXT Move if(i != 0){ Xm = i + 1 + '00'; mgn = 16 * (i + 1); } $itm.css('transform','translateX(calc(-' + Xm + '% - '+mgn+'px))'); $act.removeClass('act'); $btn.eq(i + 1).addClass('act'); $('.arTabMod-sec').height($itm.eq(i + 1).children().height()); nowTouch = false; } else if(this.left < -24){// PREV Move if(i != 0){ Xm = i - 1 + '00'; mgn = 16 * (i - 1); } $itm.css('transform','translateX(calc(-' + Xm + '% - '+mgn+'px))'); $act.removeClass('act'); $btn.eq(i - 1).addClass('act'); $('.arTabMod-sec').height($itm.eq(i - 1).children().height()); nowTouch = false; } else {// BACK Move let tX = 0; if(i != 0){tX = '-' + i + '00%';} $itm.css({ 'transform':'translateX(' + tX + ')', 'transition':'0.1s' }); } } });