CSS3の Transformを利用した立体的な表現

CSS3の Transformを利用した立体的な表現

CSS3の transformプロパティが登場したことにより拡大・縮小や回転や移動など様々な表現が可能になりました。これらを応用することで立体的で奥行きのある表現も可能になります。今回は、立体を回転させるシンプルな表現を紹介します。

transformの rotate( )関数について

要素を回転させるための関数です。X軸・Y軸・Z軸を基準に時計回りに回転させ、マイナスの値を指定した場合は逆回転します。単位には度を表す Degreeの省略である degを使用します。

CSS
/*X軸・Y軸・Z軸を基準に要素を時計回りに45度回転させる。*/
transform: rotateX(45deg) rotateY(45deg) rotateZ(45deg);

transformの translate3d( )関数について

要素を移動させるためのプロパティです。値は、X軸、Y軸、Z軸の順で指定しますが Y軸と Z軸は省略可能です。値が明示的に指定されていない場合は初期値が割りてられます。単位は主に pxや %を使用します。

CSS
/*X軸の指定のみ。Y軸とZ軸は省略する。*/
transform: translate3d(10px);

/*X軸・Y軸・Z軸の指定。*/
transform: translate3d(10px, 10px, 10px);

transform-styleについて

指定した要素の子要素が平面空間に配置されるか立体空間に配置されるかを決めます。値には flat(平面空間)と preserve-3d(立体空間)が指定できます。初期値は flatになります。

CSS
/*初期値。子要素を平面空間に配置する。*/
transform-style: flat;

/*子要素を立体空間に配置する。*/
transform-style: preserve-3d;

perspectiveと transformの perspective( )関数について

パースをつけて遠近感のある描写をします。perspectivプロパティは指定した要素の子要素が対象で、perspective( )関数は指定した要素自身が対象です。値が大きいほど遠近感が弱くなり値が大きいほど遠近感が強くなります。単位には pxを使用します。

CSS
/*perspectiveプロパティ。*/
perspective: 1000px;

/*transformプロパティの perspective()関数。*/
transform: perspective(1000px);

transform-originについて

transformに指定される関数の原点を指定します。値は、X軸、Y軸、Z軸の順で指定しますが Y軸とZ軸は省略可能です。値が明示的に指定されていない場合は初期値が割りてられます。初期値は、X軸が50% Y軸が50% Z軸が0です。単位は、pxや %の他にキーワードを使用します。

キーワード 説明
left X軸の値として指定可能。左から0%の位置。
right X軸の値として指定可能。左から100%の位置。
top Y軸の値として指定可能。上から0%の位置。
bottom Y軸の値として指定可能。上から100%の位置。
center X軸・Y軸の値として指定可能。X軸の場合は左から50%の位置。Y軸の場合は上から50%の位置。
CSS
/*初期値。X軸・Y軸・Z軸の順番で指定される。*/
transform-origin: 50% 50% 0;

/*X軸のみの指定。X軸は0 Y軸は50% Z軸は0と同じ。*/
transform-origin: left;

/*X軸と Y軸の指定。X軸は左から100px Y軸は上から100px Z軸は0と同じ。*/
transform-origin: 100px 100px;

transform-originの Z軸に値を指定した場合に表示結果が異なる

perspectiveが指定された子要素に対して transform-originの Z軸に値を指定した場合、Safariでは他のブラウザと結果が異なる場合があります。以下のコードを Chromeと Safariで比較すると違いが確認できます。

HTML
<div class="container">
<div class="surface"></div>
</div>
CSS
.container {
  border: 2px solid blue;
  margin: 200px auto;
  height: 200px;
  -webkit-perspective: 1000px;
  perspective: 1000px;
  position: relative;
  width: 200px;
}

.container .surface {
  height: 100%;
  background: rgba(0, 222, 140, 0.5);
  position: absolute;
  transform-origin: 50% 50% -200px;
  transform: translate3d(0, 0, 100px);
  width: 100%;
}

Chromeと Safariの比較

表示結果を確認するとグリーンの要素の大きさがそれぞれのブラウザで違う大きさになります。

この件に関しては Stack Overflowでも取り上げられているので以下のリンクから確認できます。

複数の要素を組み合わせて立方体を作る

このページで説明してきた CSSプロパティや関数を使用して立方体を作ります。立方体は辺の長さが等しい平面を6つ用意してそれを上下左右そして前後に割り当てて作ることができます。

HTML
<div id="demo-1">
<div class="cube">
<div class="front"></div>
<div class="left"></div>
<div class="right"></div>
<div class="back"></div>
<div class="top"></div>
<div class="bottom"></div>
</div>

クラス名 cubeの要素内に6つの要素を作り立方体の面にします。面になる要素にはクラス名 front、left、right、back、top、bottomが付いています。

CSS
#demo-1 {
  margin: 80px 0;
}

#demo-1 .cube {
  animation: rotateCube 5s infinite linear;
  height: 200px;
  margin: 0 auto;
  position: relative;
  transform: perspective(1000px);
  transform-origin: 50% 50% -100px;
  transform-style: preserve-3d;
  width: 200px;
}

@keyframes rotateCube {
  0% {
    transform: perspective(1000px) rotateX(0deg) rotateY(0deg);
  }
  
  100% {
    transform: perspective(1000px) rotateX(-360deg) rotateY(-360deg);
  }
}

#demo-1 .cube div {
  background-color: rgba(162, 176, 206, 0.1);
  border: 1px solid #A2B0CE;
  height: 200px;
  left: 0;
  position: absolute;
  top: 0;
  width: 200px;
}

/*front*/
#demo-1 .cube .front {
  position: relative;
}

/*left*/
#demo-1 .cube .left {
  transform: rotateY(-90deg) translate3d(-100px, 0, 100px);
}

/*right*/
#demo-1 .cube .right {
  transform: rotateY(90deg) translate3d(100px, 0, 100px);
}

/*back*/
#demo-1 .cube .back {
  transform: translate3d(0, 0, -200px);
}

/*top*/
#demo-1 .cube .top {
  transform: rotateX(-90deg) translate3d(0, 100px, -100px);
}

/*bottom*/
#demo-1 .cube .bottom {
  transform: rotateX(90deg) translate3d(0, -100px, -100px);
}

デモ 立体表現を使ったスライダー

立体表現を使ったシンプルなスライダーのデモです。画像切り替えの際は、transformの rotateX( )と rotateY( )のいずれかを使用して回転させます。jQueryのプラグインになっているので、設定項目は少ないですが調整が可能です。

  • スライダーのデモ画像1
  • スライダーのデモ画像2
  • スライダーのデモ画像3
  • スライダーのデモ画像4
HTML
<div id="slider-1" style="opacity: 0">
<ul>
<li><a href="#"><img src="http://web-pixy.com/images/photo-XzXzQqH0UztqdNcp.jpg" alt="スライダーのデモ画像1"></a></li>
<li><a href="#"><img src="http://web-pixy.com/images/photo-rvL6S8i9P0rRgmyTQcAyUAV9RVi8nLK4.jpg" alt="スライダーのデモ画像2"></a></li>
<li><a href="#"><img src="http://web-pixy.com/images/photo-Z9WofUbxyxyKmICEhGoLCuo2fVd3mInm.jpg" alt="スライダーのデモ画像3"></a></li>
<li><a href="#"><img src="http://web-pixy.com/images/photo-q1kNxWBw6PE0tavD0uv8Rl8b8xtoc1es.jpg" alt="スライダーのデモ画像4"></a></li>
</ul>
</div>
CSS
/*////////////////////////////////////////////////////////////////////////////////
スライダー
////////////////////////////////////////////////////////////////////////////////*/

.tdSlider {
  position: relative;
}

.tdSlider .sliderMain {
  position: relative;
  z-index: 1;
}

.tdSlider .sliderMain .sliderCell {
  backface-visibility: hidden;
  background: #E1E1E1;
  overflow: hidden;
  position: relative;
  width: 100%;
}

.tdSlider .sliderMain .sliderCell img {
  border: none;
  display: block;
  height: auto;
  width: 100%;
}

.tdSlider .sliderNavi .prev,
.tdSlider .sliderNavi .next {
  -webkit-align-items: center;
  align-items: center;
  background: #EEE;
  border-radius: 100%;
  color: #555;
  cursor: pointer;
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  display: -ms-flex;
  display: -ms-flexbox;
  display: -o-flex;
  font-size: .8em;
  height: 50px;
  -webkit-justify-content: center;
  justify-content: center;
  line-height: 1.1;
  opacity: .5;
  position: absolute;
  width: 50px;
  z-index: 2;
}

.tdSlider .sliderNavi .prev {
  left: 25px;
  top: calc(100% / 2 - 25px);
}

.tdSlider .sliderNavi .next {
  right: 25px;
  top: calc(100% / 2 - 25px);
}

.tdSlider .sliderNavi .prev img,
.tdSlider .sliderNavi .next img {
  width: 8px;
}



/*////////////////////////////////////////////////////////////////////////////////
スライダー ナビ マウスオーバー
////////////////////////////////////////////////////////////////////////////////*/

.tdSlider.hover .sliderNavi .prev,
.tdSlider.hover .sliderNavi .next {
  opacity: 1;
}

.tdSlider.touchsupport.hover .sliderNavi .prev,
.tdSlider.touchsupport.hover .sliderNavi .next {
  opacity: .5;
}



/*////////////////////////////////////////////////////////////////////////////////
スライダー ローディング中
////////////////////////////////////////////////////////////////////////////////*/

.tdSlider ul {
  position: relative;
  visibility: hidden;
  z-index: 1;
}

.tdSlider ul li {
  left: 0;
  position: absolut;
  top: 0;
  z-index: 1;
}
JavaScript
;(function($){
  
  
  
/*////////////////////////////////////////////////////////////////////////////////
スライダー
////////////////////////////////////////////////////////////////////////////////*/
  
  'use strict';
  
  (function(){//_addSlider()
    
    var ua = window.navigator.userAgent.toLowerCase();
    var s = {};
    var c = {};
        
    s.s = '.tdSlider';
    s.sv = '.sliderViewport';
    s.sm = '.sliderMain';
    s.smc = '.sliderCell';
    s.sn = '.sliderNavi';
    s.snp = '.prev';
    s.snn = '.next';
    s.h = '.hover';
    s.ntd = '.notd';
    s.p = '.pause';
    s.sw = '.swipe';
    s.t = '.transform';
    
    $.each(s, function(k, v){
      
      if(v.match(/^\./)) c[k] = v.substr(1);
    });
    
    var _tdSlider = function(t, o){
      
      var $t = $(t);
      var img = [];
      var html = '';
      
      var d = $.extend({
        
        $target: $t,
        autoPlay: true,
        direction : 'initial',
        duration : 800,
        easing : 'linear',
        interval: 5000,
        next: '<span>NEXT</span>',
        pauseOnHover: false,
        perspective: '800px',
        prev: '<span>PREV</span>',
        transform: 'rotateX'
        
      }, o);
            
      $t.find('li').children().each(function(){
        
        img.push($(this)[0]);
      });
      
      $.extend(d, {
        
        browser: ua.indexOf('edge') != -1 || ua.indexOf('firefox') != -1 ? 1: ua.indexOf('msie') != -1 || ua.indexOf('trident') != -1 ? 2 : 0,
        img: img,
        imgIndex: 0,
      });
      
      html += '<div class="' + c.sv + '">';
      html += '<div class="' + c.sm + '">';
      html += '</div>';
      html += '</div>';
      html += '<div class="' + c.sn + '">';
      html += '<div class="' + c.snp + '">' + d.prev + '</div>';
      html += '<div class="' + c.snn + '">' + d.next + '</div>';
      html += '</div>';
      
      if(d.browser == 2) $t.addClass(c.ntd);
      
      $t.addClass(c.s).children().remove();
      $t.append(html);
      
      var $sm = $t.find(s.sm);
      
      $.each(d.img, function(i){
        
        $sm.append('<div class="' + c.smc + '">' + $(this)[0].outerHTML + '</div>');
        
        $sm.children().not(':first').css({
          
          'left': 0,
          'position': 'absolute',
          'top': 0
        });
      });
      
      if('ontouchstart' in window) $t.addClass('touchsupport');
      
      $sm.imagesLoaded(function(e){
        
        $sm.children().not(':first').remove();
        
        $t.css({
          
          'opacity': 1,
          'transition': 'opacity .8s'
        });
        
        _addEvents($t, d);
        _swipe.init($t, d, s, c);
        _autoPlay($t, d);
      });
    };//_tdSlider()
    
    function _autoPlay($t, d){
      
      if(!d.autoPlay) return;
      
      var ist = 'ontouchstart' in window;
      var tid = false;
      var iid = false;
      
      $t.find([s.snp, s.snn].join(',')).on('click', function(e){
        
        _stop();
        _start(d.duration);
      });
      
      $t.find(s.sv).on('mouseenter mouseleave', function(e){
        
        if(!ist){
          
          if(e.type == 'mouseenter'){
            
            if(d.pauseOnHover) $t.addClass(c.p);
              
            _stop();
          }
          
          if(e.type == 'mouseleave'){
            
            if(d.pauseOnHover) $t.removeClass(c.p);
           
            _start();
          }
        }
      });
      
      $t.find(s.sm).on('touchstart touchend', function(e){
        
        if(e.type == 'touchstart') _stop();
        if(e.type == 'touchend') _start();
      });
      
      function _start(du){
        
        tid = setTimeout(function(){
          
          if(!$t.hasClass(c.sw) && !$t.hasClass(c.t) && !$t.hasClass(c.p)) _animation($t, d);
          
          _start(d.duration);
          
        }, du ? du + d.interval : d.interval);
      };//_start()
      
      function _stop(){
        
        clearTimeout(tid);
      };//_stop()
      
      _start();
    };//_autoPlay()    
        
    function _addEvents($t, d){
      
      $t.find([s.snp, s.snn].join(',')).on('click', function(e){
        
        if($(this).parents(s.s).hasClass('transform')) return;
        
        _animation($t, d, e);
      });
      
      $t.find([s.sv, s.snp, s.snn].join(',')).on('ontouchstart' in window ? 'touchstart touchend' : 'mouseenter mouseleave', function(e){
        
        if(e.type == 'mouseenter' || e.type == 'touchstart') $t.addClass(c.h);
        if(e.type == 'mouseleave' || e.type == 'touchend') $t.removeClass(c.h);
      });
    };//_addEvents()
    
    function _animation($t, d, e){
      
      var $sm = $t.find(s.sm);
      var html = '';
            
      html += '<div class="' + c.smc + '">' + d.img[_getImgIndex(0, d)].outerHTML + '</div>';
      html += '<div class="' + c.smc + '">' + d.img[_getImgIndex(1, d)].outerHTML + '</div>';
      
      if(d.browser != 2){
        
        html += '<div class="' + c.smc + '"></div>';
        html += '<div class="' + c.smc + '"></div>';
        html += '<div class="' + c.smc + '"></div>';
      }
      
      $sm.append(html);
      
      var $smc = $sm.find(s.smc);
      var dr = e ? $(e.currentTarget).hasClass(c.snp) ? 0 : 1 : 1;
      var css, tp, tn;
      
      d.imgIndex = _paging(dr, d);
      
      $t.addClass([c.t, d.transform, dr ? c.snn : c.snp].join(' '));
      _transformStart($t, d);
      _setTimeout(d.duration).then(function(){_transformEnd($t, d)});
    };//_animation()
    
    function _transformStart($t, d){
      
      var $sv = $t.find(s.sv);
      var $sm = $t.find(s.sm);
      var $smc = $sm.find(s.smc);
      var dr = $t.hasClass(c.snp) ? 0 : 1;
      
      if(d.browser == 2){
        
        _ie();
        
      }else{
        
        if(d.transform == 'rotateX') _rotateX();
        if(d.transform == 'rotateY') _rotateY();
      }
      
      function _rotateX(){
        
        $sv.css({'cssText': 'perspective: ' + d.perspective});
        $sm.css({'transform-style': 'preserve-3d'});
        
        $smc.not(':eq(0)').css({
          
          'left': 0,
          'position': 'absolute',
          'top': 0
        });
        
        if(d.direction == 'btt'){
          
          $smc.eq(0).css({
            
            'height': $sm.outerHeight(),
            'width': $sm.outerWidth()
          });
          
          $smc.eq(1).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateX(90deg) translate3d(0, ' + -$sm.outerHeight() + 'px, 0px)',
            'transform-origin': 'top',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(2).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateX(-90deg) translate3d(0, 0, ' + $sm.outerHeight() + 'px)',
            'transform-origin': 'top',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(3).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(180deg) translate3d(0, 0, ' + $sm.outerHeight() + 'px)',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(4).css({
          
            'height': $sm.outerHeight(),
            'transform': 'rotateY(-90deg) translate3d(' + -$sm.outerHeight() + 'px, 0, 0)',
            'transform-origin': 'left',
            'width': $sm.outerHeight()
          });
          
          $smc.eq(5).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(90deg) translate3d(0, 0, ' + $sm.outerWidth() + 'px)',
            'transform-origin': 'left',
            'width': $sm.outerHeight()
          });
                    
          $sm.css(
            
            dr ? {//next
              
              'transform': 'rotateX(90deg) translate3d(0, ' + -$sm.outerHeight() / 2 + 'px, ' + $sm.outerHeight() / 2 + 'px)',
              'transition': 'all ' + d.duration + 'ms ' + d.easing
              
            } : {//prev
              
              'transform': 'rotateX(-90deg) translate3d(0, ' + $sm.outerHeight() / 2 + 'px, ' + $sm.outerHeight() / 2 + 'px)',
              'transition': 'all ' + d.duration + 'ms ' + d.easing
            }
          );
          
        }else{
          
          $smc.eq(0).css({
            
            'height': $sm.outerHeight(),
            'width': $sm.outerWidth()
          });
          
          $smc.eq(1).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateX(-90deg) translate3d(0, 0, ' + $sm.outerHeight() + 'px)',
            'transform-origin': 'top',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(2).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateX(90deg) translate3d(0, ' + -$sm.outerHeight() + 'px, 0px)',
            'transform-origin': 'top',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(3).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(180deg) translate3d(0, 0, ' + $sm.outerHeight() + 'px)',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(4).css({
          
            'height': $sm.outerHeight(),
            'transform': 'rotateY(-90deg) translate3d(' + -$sm.outerHeight() + 'px, 0, 0)',
            'transform-origin': 'left',
            'width': $sm.outerHeight()
          });
          
          $smc.eq(5).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(90deg) translate3d(0, 0, ' + $sm.outerWidth() + 'px)',
            'transform-origin': 'left',
            'width': $sm.outerHeight()
          });
          
          $sm.css(
            
            dr ? {//next
              
              'transform': 'rotateX(-90deg) translate3d(0, ' + $sm.outerHeight() / 2 + 'px, ' + $sm.outerHeight() / 2 + 'px)',
              'transition': 'all ' + d.duration + 'ms ' + d.easing,
              
            } : {//prev
              
              'transform': 'rotateX(90deg) translate3d(0, ' + -$sm.outerHeight() / 2 + 'px, ' + $sm.outerHeight() / 2 + 'px)',
              'transition': 'all ' + d.duration + 'ms ' + d.easing,
            }
          );
        }
      };//_rotateX()
      
      function _rotateY(){
        
        $sv.css({'cssText': 'perspective: ' + d.perspective});
        $sm.css({'transform-style': 'preserve-3d'});
        
        $smc.not(':eq(0)').css({
          
          'left': 0,
          'position': 'absolute',
          'top': 0
        });
        
        if(d.direction == 'ltr'){
          
          $smc.eq(0).css({
            
            'height': $sm.outerHeight(),
            'width': $sm.outerWidth()
          });
          
          $smc.eq(1).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(90deg) translate3d(0, 0, ' + $sm.outerWidth() + 'px)',
            'transform-origin': 'left',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(2).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(-90deg) translate3d(' + -$sm.outerWidth() + 'px, 0, 0)',
            'transform-origin': 'left',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(3).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(180deg) translate3d(0, 0, ' + $sm.outerWidth() + 'px)',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(4).css({
            
            'height': $sm.outerWidth(),
            'transform': 'rotateX(90deg) translate3d(0, ' + -$sm.outerWidth() + 'px, 0)',
            'transform-origin': 'top',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(5).css({
            
            'height': $sm.outerWidth(),
            'transform': 'rotateX(-90deg) translate3d(0, 0, ' + $sm.outerHeight() + 'px)',
            'transform-origin': 'top',
            'width': $sm.outerWidth()
          });
          
          $sm.css(dr ? {//next
            
            'transform': 'rotateY(90deg) translate3d(' + $sm.outerWidth() / 2 + 'px, 0, ' + $sm.outerWidth() / 2 + 'px)',
            'transition': 'all ' + d.duration + 'ms ' + d.easing,
            
          } : {//prev
            
            'transform': 'rotateY(-90deg)  translate3d(' + -$sm.outerWidth() / 2 + 'px, 0, ' + $sm.outerWidth() / 2 + 'px)',
            'transition': 'all ' + d.duration + 'ms ' + d.easing,
          });
                              
        }else{
          
          $smc.eq(0).css({
            
            'height': $sm.outerHeight(),
            'width': $sm.outerWidth()
          });
          
          $smc.eq(1).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(-90deg) translate3d(' + -$sm.outerWidth() + 'px, 0, 0)',
            'transform-origin': 'left',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(2).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(90deg) translate3d(0, 0, ' + $sm.outerWidth() + 'px)',
            'transform-origin': 'left',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(3).css({
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(180deg) translate3d(0, 0, ' + $sm.outerWidth() + 'px)',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(4).css({
            
            'height': $sm.outerWidth(),
            'transform': 'rotateX(90deg) translate3d(0, ' + -$sm.outerWidth() + 'px, 0)',
            'transform-origin': 'top',
            'width': $sm.outerWidth()
          });
          
          $smc.eq(5).css({
            
            'height': $sm.outerWidth(),
            'transform': 'rotateX(-90deg) translate3d(0, 0, ' + $sm.outerHeight() + 'px)',
            'transform-origin': 'top',
            'width': $sm.outerWidth()
          });
          
          $sm.css(dr ? {//next
            
            'height': $sm.outerHeight(),
            'transform': 'rotateY(-90deg)  translate3d(' + -$sm.outerWidth() / 2 + 'px, 0, ' + $sm.outerWidth() / 2 + 'px)',
            'transition': 'all ' + d.duration + 'ms ' + d.easing,
            'width': $sm.outerWidth()
            
          } : {//prev
            
            'transform': 'rotateY(90deg)  translate3d(' + $sm.outerWidth() / 2 + 'px, 0, ' + $sm.outerWidth() / 2 + 'px)',
            'transition': 'all ' + d.duration + 'ms ' + d.easing,
          });
        }
      };//_rotateY()
      
      function _ie(){
        
        $sv.css({'overflow': 'hidden'});
        $sm.css({'transform-style': 'flat'});
        $smc.eq(0).css({'position': 'relative'});
        
        $smc.eq(1).css({
          
          'left': '-100%',
          'position': 'absolute',
          'top': 0
        });
        
        $smc.eq(2).css({
          
          'left': '100%',
          'position': 'absolute',
          'top': 0
        });
        
        $sm.css(dr ? {//next
          
          'height': $sm.outerHeight(),
          'transform': 'translateX(' + -$sm.outerWidth() + 'px)',
          'transition': 'all ' + d.duration + 'ms ' + d.easing,
          'width': $sm.outerWidth()
          
        } : {//prev
          
          'height': $sm.outerHeight(),
          'transform': 'translateX(' + $sm.outerWidth() + 'px)',
          'transition': 'all ' + d.duration + 'ms ' + d.easing,
          'width': $sm.outerWidth()
        });
      };//_ie()
    };//_transformStart()
    
    function _transformEnd($t, d){
      
      var $sv = $t.find(s.sv);
      var $sm = $t.find(s.sm);
      var $smc = $sm.find(s.smc);
      var dr = $t.hasClass(c.snp) ? 0 : 1;
      
      if(d.browser == 2){
        
        _ie();
        
      }else{
        
        _rotate();
      }
      
      function _rotate(){
        
        $sv.css({'perspective': ''});
        $sm.css({'transform-style': ''});
        $smc.not($smc.eq(dr ? 2 : 1)).remove();
        
        $sm.css({
          
          'transform': '',
          'transform-origin': '',
          'transition': ''
        });
        
        $smc.css({
          
          'height': '',
          'left': '',
          'position': '',
          'top': '',
          'transform': '',
          'transform-origin': '',
          'transition': '',
          'width': ''
        });
        
        $t.removeClass([c.t, d.transform, c.snp, c.snn].join(' '));
      };//_rotate()
      
      function _ie(){
        
        $sv.css({'overflow': ''});
        
        $sm.css({
          
          'height': '',
          'transform': '',
          'transform-style': '',
          'transition': '',
          'width': ''
        });
        
        $smc.not($smc.eq(dr ? 2 : 1)).remove();
        
        $smc.css({
          
          'left': '',
          'position': '',
          'top': ''
        });
        
        $t.removeClass([c.t, d.transform, c.snp, c.snn].join(' '));
      };//_ie();
    }//_transformEnd()
    
    function _getImgIndex(dr, d){
      
      return dr ? d.imgIndex + 1 > d.img.length - 1 ? 0 : d.imgIndex + 1 : d.imgIndex - 1 < 0 ? d.img.length - 1 : d.imgIndex - 1;
    };//_getImgIndex()
    
    function _paging(dr, d){
      
      return dr ? ++d.imgIndex > d.img.length -1 ? 0 : d.imgIndex : --d.imgIndex < 0 ? d.img.length - 1 : d.imgIndex;
    };//_paging()
    
    function _setTimeout(s){
      
      var df = new $.Deferred();
      
      setTimeout(function(){
        
        df.resolve();
        
      }, s);
      
      return df.promise();
    };//_setTimeout()
    
    $.fn._tdSlider = function(o){
      
      $.each(this, function(){
        
        new _tdSlider(this, o);
      });
    };//_tdSlider()
    
    var _swipe = (function(){
      
      var s = {};
      var c = {};
      var xs, xc;
      
      $.each(s, function(k, v){
        
        if(v.match(/^\./)) c[k] = v.substr(1);
      });
      
      var d = {
        
        isd: false,
        dr: false,
        du: 200,
        es: 'linear',
        pm: 0,
        sp: {x: 0, y: 0},
        te: (window.navigator.msPointerEnabled) ? 'MSPointerUp' : 'touchend',
        tm: (window.navigator.msPointerEnabled) ? 'MSPointerMove' : 'touchmove',
        ts: (window.navigator.msPointerEnabled) ? 'MSPointerDown' : 'touchstart',
      };
      
      function _init($t, xd, _xs, _xc){
        
        xs = _xs;
        xc = _xc;
        
        var $v = $t.find(xs.sv);
        var $m = $t.find(xs.sm);
        
        $m.on([d.ts, d.tm, d.te].join(' '), function(e){
          
          if($t.hasClass('transform')) return;
          
          //touch start
          if(e.type == d.ts){
            
            d.isd = true;
            d.pm = 0;
            d.sp.x = (e.pageX !== undefined) ? e.pageX : e.originalEvent.touches[0].pageX;
            d.sp.y = (e.pageY !== undefined) ? e.pageY : e.originalEvent.touches[0].pageY;
            
            $t.addClass(xc.sw);
            $v.css({'overflow': 'hidden'});
            $m.css({'position': 'relative'}).append(_getHTML($t, xd));
            
            var $c = $t.find(xs.smc);
            
            $c.eq(0).css({'position': 'static'});
            
            $c.eq(1).css({
              
              'left': '-100%',
              'position': 'absolute',
              'top': 0,
              'z-index': 1
            });
            
            $c.eq(2).css({
              
              'left': '100%',
              'position': 'absolute',
              'top': 0,
              'z-index': 1
            });
          }//touch start
          
          //touch move
          if(e.type == d.tm){
            
            e.preventDefault();
            
            var x = (e.pageX !== undefined) ? e.pageX : e.originalEvent.touches[0].pageX;
            
            d.pm = (d.sp.x - x) / $t.find(xs.sv).outerWidth() * 100;
            
            if(d.isd){
              
              if(d.pm > 35){
               
               if(!$t.hasClass(xc.t)){
                
                d.isd = false;
                xd.imgIndex = _paging(1, xd);
                
                 _next($t, d);
               }
                
              }else if(d.pm < -35){
                
                if(!$t.hasClass(xc.t)){
                  
                  d.isd = false;
                  xd.imgIndex = _paging(0, xd)
                  
                  _prev($t, d);
                }
                
              }else{
                
                if(!$t.hasClass(xc.t)) _manual($t, d);
              }
            }
          }//touch move
          
          //touch end
          if(e.type == d.te){
            
            d.isd = false;
            
            if(!$t.hasClass(xc.t)) _reset($t, d);
          }//touch end
        });
      };//_init();
      
      function _manual($t, d){ 
        
        $t.find(xs.sm).css({'transform': 'translateX(' + -d.pm + '%' + ')'});
      };//_manual()
      
      function _reset($t, c){
        
        var $v = $t.find(xs.sv);
        var $m = $t.find(xs.sm);
        
        $m.css({
          
          'transform': 'translateX(0)',
          'transition': 'transform ' + d.du + 'ms ' + d.es
        });
        
        _setTimeout(d.du).then(function(){
          
          var $c = $t.find(xs.smc);
          
          $m.css({
            
            'position': '',
            'transform': '',
            'transition': '',
            'width': '',
          });
          
          $c.css({
            
            'left': '',
            'position': '',
            'top': '',
            'transform': '',
            'transition': '',
            'width': '',
            'z-index': ''
            
          }).not(':eq(0)').remove();
          
          $v.css({'overflow': ''});
          $t.removeClass([xc.t, xc.sw].join(' '));
        });
      };//_reset()
      
      function _prev($t, d){
        
        var $v = $t.find(xs.sv);
        var $m = $t.find(xs.sm);
        
        $t.addClass(xc.t);
        
        $m.css({
          
          'transform': 'translateX(100%)',
          'transition': 'transform ' + d.du + 'ms ' + d.es
        });
        
        _setTimeout(d.du).then(function(){
          
          var $c = $t.find(xs.smc);
          
          $m.css({
            
            'position': '',
            'transform': '',
            'transition': '',
            'width': '',
          });
          
          $c.css({
            
            'left': '',
            'position': '',
            'top': '',
            'transform': '',
            'transition': '',
            'width': '',
            'z-index': ''
            
          }).not(':eq(1)').remove();
          
          $v.css({'overflow': ''});
          $t.removeClass([xc.t, xc.sw].join(' '));
        });
      };//_prev()
      
      function _next($t, d){
        
        var $v = $t.find(xs.sv);
        var $m = $t.find(xs.sm);
        
        $t.addClass(xc.t);
        
        $m.css({
          
          'transform': 'translateX(-100%)',
          'transition': 'transform ' + d.du + 'ms ' + d.es
        });
        
        _setTimeout(d.du).then(function(){
          
          var $c = $t.find(xs.smc);
          
          $m.css({
            
            'position': '',
            'transform': '',
            'transition': '',
            'width': '',
          });
          
          $c.css({
            
            'left': '',
            'position': '',
            'top': '',
            'transform': '',
            'transition': '',
            'width': '',
            'z-index': ''
            
          }).not(':eq(2)').remove();
          
          $v.css({'overflow': ''});
          $t.removeClass([xc.t, xc.sw].join(' '));
        });
      };//_next()
      
      function _getHTML($t, d){
        
        var $m = $t.find(xs.sm);
        var html = '';
        
        html += '<div class="' + xc.smc + '">' + d.img[_getImgIndex(0, d)].outerHTML + '</div>';
        html += '<div class="' + xc.smc + '">' + d.img[_getImgIndex(1, d)].outerHTML + '</div>';
        
        return html;
      };//_getHTML()
            
      return {init: _init};
    }());//_swipe()
  }());//_addSlider()
}(jQuery));

$(function(){
  
  $('#demo-2 #slider-1')._tdSlider({
    
    autoPlay: true,
    interval: 5000,
    duration: 1000,
    easing: 'cubic-bezier(0.86, 0, 0.07, 1)',
    next: '<img src="http://web-pixy.com/images/site/icon-arrow-right-1.svg" alt="next">',
    pauseOnHover: true,
    perspective: '2000px',
    prev: '<img src="http://web-pixy.com/images/site/icon-arrow-left-1.svg" alt="previous">',
    transform: 'rotateX',
  });
});
スライダーのオプション
オプション 初期値 説明
autoPlay true スライダーの内容を自動で切り替えるか。切り替えない場合は falseを指定。
direction 'initial' 変形の方向を指定する。transformの値が rotateXの場合 initialで上から下へ、bttで下からから上へ。transformの値が rotateYの場合 initialで右から左へ、ltrで左から右へ。文字列で指定する。
duration 800 エフェクトのスピードをミリ秒で指定。
easing 'linear' イージングの種類。文字列で指定する。
interval 5000 次の内容を表示させるまでの間隔をミリ秒で指定。
next '<span>NEXT</span>' ナビゲーターの次への指定。文字列で指定する。
pauseOnHover false マウスオーバーした際に自動切り替えを止めるかの指定。
perspective '800px' CSSの perspectiveプロパティの指定。文字列で pxをつけて指定する。
prev '<span>PREV</span>' ナビゲーターの前への指定。文字列で指定する。
transform 'rotateX' 変形の種類を指定。 rotateXで縦の変形、rotateYで横の変形。文字列て指定する。

デモ 立体表現を使ったヘッダー

立体表現を使ったヘッダーのデモです。メニューにマウスオーバーすると X軸を中心に回転します。

HTML
<div id="demoHeader">
<ul id="demoHeaderNavi">
<li>
<a href="#">
<div class="demoHeaderNaviBox">
<div class="demoHeaderNaviBox-1"><span>HOME</span></div>
<div class="demoHeaderNaviBox-2"><span>HOME</span></div>
</div>
</a>
</li>
<li>
<a href="#">
<div class="demoHeaderNaviBox">
<div class="demoHeaderNaviBox-1"><span>PRODUCTS</span></div>
<div class="demoHeaderNaviBox-2"><span>PRODUCTS</span></div>
</div>
</a>
</li>
<li>
<a href="#">
<div class="demoHeaderNaviBox">
<div class="demoHeaderNaviBox-1"><span>FEATURE</span></div>
<div class="demoHeaderNaviBox-2"><span>FEATURE</span></div>
</div>
</a>
</li>
<li>
<a href="#">
<div class="demoHeaderNaviBox">
<div class="demoHeaderNaviBox-1"><span>NEWS</span></div>
<div class="demoHeaderNaviBox-2"><span>NEWS</span></div>
</div>
</a>
</li>
<li>
<a href="#">
<div class="demoHeaderNaviBox">
<div class="demoHeaderNaviBox-1"><span>BLOG</span></div>
<div class="demoHeaderNaviBox-2"><span>BLOG</span></div>
</div>
</a>
</li>
</ul>
</div>
CSS
/*////////////////////////////////////////////////////////////////////////////////
ヘッダー
////////////////////////////////////////////////////////////////////////////////*/

#demoHeader {
  overflow: hidden;
  padding: 15px 0;
}

#demoHeaderNavi {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -moz-flex;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-wrap: nowrap;
  flex-wrap: nowrap;
  font-family: 'Anton', sans-serif;
  justify-content: center;
  -webkit-perspective: 600px;
  perspective: 600px;
  position: relative;
  z-index: 1;
}

#demoHeaderNavi li {
  width: 20%;
}

#demoHeaderNavi a {
  display: block;
  height: 50px;
}

#demoHeaderNavi li:nth-child(1) .demoHeaderNaviBox {
  z-index: 1;
}

#demoHeaderNavi li:nth-child(2) .demoHeaderNaviBox {
  z-index: 2;
}

#demoHeaderNavi li:nth-child(3) .demoHeaderNaviBox {
  z-index: 3;
}

#demoHeaderNavi li:nth-child(4) .demoHeaderNaviBox {
  z-index: 2;
}

#demoHeaderNavi li:nth-child(5) .demoHeaderNaviBox {
  z-index: 1;
}

#demoHeaderNavi .demoHeaderNaviBox {
  margin: 0 auto;
  position: relative;
  transform-origin: center 25px -25px;
  transform-style: preserve-3d;
}

#demoHeaderNavi [class*=demoHeaderNaviBox-],
#demoHeaderNavi [class*=demoHeaderNaviBox-]:before,
#demoHeaderNavi [class*=demoHeaderNaviBox-]:after {
  background-color: #444;
  position: absolute;
  -webkit-backface-visibility: hidden;
  transform-style: preserve-3d;
}

#demoHeaderNavi [class*=demoHeaderNaviBox-]:before,
#demoHeaderNavi [class*=demoHeaderNaviBox-]:after {
  content: "";
}

#demoHeaderNavi [class*=demoHeaderNaviBox-] {
  height: 50px;
  width: 100.2%;
  z-index: 1;
}

#demoHeaderNavi .demoHeaderNaviBox-1 {
  color: #FFF;
}

#demoHeaderNavi .demoHeaderNaviBox-1:before,
#demoHeaderNavi .demoHeaderNaviBox-1:after {
  height: 50px;
  left: 0;
  top: 0;
  width: 100%;
}

#demoHeaderNavi .demoHeaderNaviBox-1:before {
  transform: rotateX(0deg) rotateY(180deg) rotateZ(0deg) translate3d(0, 0, 50px);
}

#demoHeaderNavi .demoHeaderNaviBox-1:after {
  transform: rotateX(90deg) rotateY(0deg) rotateZ(0deg) translate3d(0, -25px, 25px);
}

#demoHeaderNavi .demoHeaderNaviBox-2 {
  color: #DDD;
  transform: rotateX(-90deg) rotateY(0deg) rotateZ(0deg) translate3d(0, 25px, 25px);
}

#demoHeaderNavi .demoHeaderNaviBox-2:before,
#demoHeaderNavi .demoHeaderNaviBox-2:after {
  height: 50px;
  left: 0;
  top: 0;
  width: 50px;
}

#demoHeaderNavi .demoHeaderNaviBox-2:before {
  transform: rotateX(0deg) rotateY(-90deg) rotateZ(0deg) translate3d(-25px, 0, 25px);
}

#demoHeaderNavi .demoHeaderNaviBox-2:after {
  left: auto;
  right: 0;
  transform: rotateX(90deg) rotateY(90deg) rotateZ(0deg) translate3d(0, -25px, 25px);
}

#demoHeaderNavi .demoHeaderNaviBox span {
  -webkit-align-items: center;
  align-items: center;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -moz-flex;
  display: -webkit-flex;
  display: flex;
  height: 100%;
  -webkit-justify-content: center;
  justify-content: center;
  width: 100%;
}



/*////////////////////////////////////////////////////////////////////////////////
ヘッダー マウスオーバー
////////////////////////////////////////////////////////////////////////////////*/

#demoHeaderNavi a:hover .demoHeaderNaviBox {
  -webkit-animation: rotate-1 .5s cubic-bezier(1, 0, 0, 1) forwards;
  animation: rotate-1 .5s cubic-bezier(1, 0, 0, 1) forwards;
  -ms-animation: none;
}

#demoHeaderNavi a:hover [class*=demoHeaderNaviBox-]:before,
#demoHeaderNavi a:hover [class*=demoHeaderNaviBox-]:after {
  background: #666;
}

@-webkit-keyframes rotate-1 {
  to {
    transform: rotateX(90deg) rotateY(0deg) rotateZ(0deg) translate3d(0, 0, 0);
  }
}

@keyframes rotate-1 {
  to {
    transform: rotateX(90deg) rotateY(0deg) rotateZ(0deg) translate3d(0, 0, 0);
  }
}



/*////////////////////////////////////////////////////////////////////////////////
ヘッダー 360px以下
////////////////////////////////////////////////////////////////////////////////*/

@media screen and (max-width: 360px) {
  #demoHeaderNavi {
    font-size: .8em;
  }
}



/*////////////////////////////////////////////////////////////////////////////////
ヘッダー Edgeと Firefox
////////////////////////////////////////////////////////////////////////////////*/

#demoHeaderNavi.firefox,
#demoHeaderNavi.ms-edge {
  -webkit-perspective: none;
  perspective: none;
}

#demoHeaderNavi.firefox a,
#demoHeaderNavi.ms-edge a {
  perspective: 600px;
}
JavaScript
$(function(){
  
  
  
/*////////////////////////////////////////////////////////////////////////////////
ヘッダー
////////////////////////////////////////////////////////////////////////////////*/
  
  (function(){
    
    'use strict';
    
    var ua = window.navigator.userAgent.toLowerCase();
    
    if(ua.indexOf('edge') != -1){
      
      $('#demoHeaderNavi').addClass('ms-edge');
      
    }else if(ua.indexOf('firefox') != -1){
      
      $('#demoHeaderNavi').addClass('firefox');
      
    }else if(ua.indexOf('trident') != -1){
      
      $('#demoHeaderNavi .demoHeaderNaviBox span').css({
        
        'left': 0,
        'position': 'absolute',
        'right': 0,
        'z-index': 1
      });
    }
  }());
});
ページの先頭へ