cssAudio - ActiveCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - Activehtmlicon-personicon-teamoctocatspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <!-- Images from Dribbble: https://dribbble.com/Rishavmalla -->

<div class="container">
  <h1 class="heading">3D Parallax Hover Effect</h1>
  <div class="card">

    <div class="card__item">
      <h2 class="card__item-title">Time for a vacation</h2>
      <a href="https://dribbble.com/shots/2792589-Time-for-a-vacation" title="Time for a vacation">
        <div class="atvImg">
          <img src="https://d13yacurqjgara.cloudfront.net/users/1085581/screenshots/2792589/for_dribbble-01.png">

          <div class="atvImg-layer" data-img="https://d13yacurqjgara.cloudfront.net/users/1085581/screenshots/2792589/for_dribbble-01.png"></div>

        </div>

      </a>
    </div>
    <div class="card__item">
      <h2 class="card__item-title">Singha Durbar</h2>
      <a href="https://dribbble.com/shots/2787693-Singha-Durbar" title="Singha Durbar">
        <div class="atvImg">
          <img src="https://d13yacurqjgara.cloudfront.net/users/1085581/screenshots/2787693/singha_durbar_final-02-02-02.png">

          <div class="atvImg-layer" data-img="https://d13yacurqjgara.cloudfront.net/users/1085581/screenshots/2787693/singha_durbar_final-02-02-02.png"></div>

        </div>
      </a>

    </div>
    <div class="card__item">
      <h2 class="card__item-title">Little Miss Sunshine</h2>
      <a href="https://dribbble.com/shots/3002552-Little-Miss-Sunshine" title="Little Miss Sunshine">
        <div class="atvImg">
          <img src="https://d13yacurqjgara.cloudfront.net/users/1085581/screenshots/3002552/little_miss_sunshine-01.png">

          <div class="atvImg-layer" data-img="https://d13yacurqjgara.cloudfront.net/users/1085581/screenshots/3002552/little_miss_sunshine-01.png"></div>

        </div>
      </a>

    </div>

  </div>
</div>
            
          
!
            
              @import url('https://fonts.googleapis.com/css?family=Amaranth|Dancing+Script');

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  background: #43cea2;
  /* fallback for old browsers */
  background: -webkit-linear-gradient(to left, #43cea2, #185a9d);
  /* Chrome 10-25, Safari 5.1-6 */
  background: linear-gradient(to left, #43cea2, #185a9d);
  /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
  font-family: 'Dancing Script', cursive;
}

.heading {
  text-align: center;
  color: #fff;
  font-size: 60px;
  font-family: 'Amaranth', sans-serif;
}

.card {
  display: flex;
  justify-content: space-around;
  flex-wrap: wrap;
  max-width: 960px;
  margin: 0 auto;
  padding: 50px 20px 0;
}

.card__item {
  width: 29%;
  margin: 10px 20px;
}

.card__item-title {
  text-align: center;
  color: #fff;
  font-weight: normal;
  font-size: 20px;
  letter-spacing: 1px;
}

.atvImg {
  border-radius: 5px;
  transform-style: preserve-3d;
  -webkit-tap-highlight-color: rgba(#000, 0);
  width: 100%;
  height: 350px;
  display: inline-block;
  img {
    border-radius: 5px;
    box-shadow: 0 2px 8px rgba(14, 21, 47, 0.25);
  }
}

.atvImg-container {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 5px;
  transition: all 0.2s ease-out;
  &.over {
    .atvImg-shadow {
      box-shadow: 0 45px 100px rgba(14, 21, 47, 0.4), 0 16px 40px rgba(14, 21, 47, 0.4);
    }
  }
}

.atvImg-layers {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 5px;
  overflow: hidden;
  transform-style: preserve-3d;
}

.atvImg-rendered-layer {
  position: absolute;
  width: 104%;
  height: 104%;
  top: -2%;
  left: -2%;
  background-repeat: no-repeat;
  background-position: center;
  background-color: transparent;
  background-size: cover;
  transition: all 0.1s ease-out;
}

.atvImg-shadow {
  position: absolute;
  top: 5%;
  left: 5%;
  width: 90%;
  height: 90%;
  transition: all 0.2s ease-out;
  box-shadow: 0 8px 30px rgba(14, 21, 47, 0.6);
}

.atvImg-shine {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: 5px;
  background: linear-gradient(135deg, rgba(255, 255, 255, .25) 0%, rgba(255, 255, 255, 0) 60%);
}
            
          
!
            
              /*
 * atvImg
 * Copyright 2015 Drew Wilson
 * http://drewwilson.com
 *
 * Version 1.1 - Updated: Oct. 26, 2015
 */

function FastClick(e, t) {
  function n(e, t) {
    return function() {
      return e.apply(t, arguments)
    }
  }
  var i;
  t = t || {}, this.trackingClick = !1, this.trackingClickStart = 0, this.targetElement = null, this.touchStartX = 0, this.touchStartY = 0, this.lastTouchIdentifier = 0, this.touchBoundary = t.touchBoundary || 10, this.layer = e, this.tapDelay = t.tapDelay || 200, FastClick.notNeeded(e) || (deviceIsAndroid && (e.addEventListener("mouseover", n(this.onMouse, this), !0), e.addEventListener("mousedown", n(this.onMouse, this), !0), e.addEventListener("mouseup", n(this.onMouse, this), !0)), e.addEventListener("click", n(this.onClick, this), !0), e.addEventListener("touchstart", n(this.onTouchStart, this), !1), e.addEventListener("touchmove", n(this.onTouchMove, this), !1), e.addEventListener("touchend", n(this.onTouchEnd, this), !1), e.addEventListener("touchcancel", n(this.onTouchCancel, this), !1), Event.prototype.stopImmediatePropagation || (e.removeEventListener = function(t, n, i) {
    var a = Node.prototype.removeEventListener;
    "click" === t ? a.call(e, t, n.hijacked || n, i) : a.call(e, t, n, i)
  }, e.addEventListener = function(t, n, i) {
    var a = Node.prototype.addEventListener;
    "click" === t ? a.call(e, t, n.hijacked || (n.hijacked = function(e) {
      e.propagationStopped || n(e)
    }), i) : a.call(e, t, n, i)
  }), "function" == typeof e.onclick && (i = e.onclick, e.addEventListener("click", function(e) {
    i(e)
  }, !1), e.onclick = null))
}

function atvImg() {
  function e(e, t, n, i, a, s) {
    var c = o.scrollTop || r.scrollTop,
      l = o.scrollLeft,
      d = t ? e.touches[0].pageX : e.pageX,
      u = t ? e.touches[0].pageY : e.pageY,
      h = n.getBoundingClientRect(),
      v = n.clientWidth || n.offsetWidth || n.scrollWidth,
      p = n.clientHeight || n.offsetHeight || n.scrollHeight,
      m = 320 / v,
      f = .52 - (d - h.left - l) / v,
      g = .52 - (u - h.top - c) / p,
      k = u - h.top - c - p / 2,
      C = d - h.left - l - v / 2,
      E = (f - C) * (.07 * m),
      y = (k - g) * (.1 * m),
      S = "rotateX(" + y + "deg) rotateY(" + E + "deg)",
      I = Math.atan2(k, C),
      T = 180 * I / Math.PI - 90;
    0 > T && (T += 360), -1 != n.firstChild.className.indexOf(" over") && (S += " scale3d(1.07,1.07,1.07)"), n.firstChild.style.transform = S, s.style.background = "linear-gradient(" + T + "deg, rgba(255,255,255," + (u - h.top - c) / p * .4 + ") 0%,rgba(255,255,255,0) 80%)", s.style.transform = "translateX(" + f * a - .1 + "px) translateY(" + g * a - .1 + "px)";
    for (var w = a, F = 0; a > F; F++) i[F].style.transform = "translateX(" + f * w * (2.5 * F / m) + "px) translateY(" + g * a * (2.5 * F / m) + "px)", w--
  }

  function t(e, t) {
    t.firstChild.className += " over"
  }

  function n(e, t, n, i, a) {
    var o = t.firstChild;
    o.className = o.className.replace(" over", ""), o.style.transform = "", a.style.cssText = "";
    for (var r = 0; i > r; r++) n[r].style.transform = ""
  }
  var i = document,
    a = i.documentElement,
    o = i.getElementsByTagName("body")[0],
    r = i.getElementsByTagName("html")[0],
    s = window,
    c = i.querySelectorAll(".atvImg"),
    l = c.length,
    d = "ontouchstart" in s || navigator.msMaxTouchPoints;
  if (!(0 >= l))
    for (var u = 0; l > u; u++) {
      var h = c[u],
        v = h.querySelectorAll(".atvImg-layer"),
        p = v.length;
      if (!(0 >= p)) {
        for (; h.firstChild;) h.removeChild(h.firstChild);
        var m = i.createElement("div"),
          f = i.createElement("div"),
          g = i.createElement("div"),
          k = i.createElement("div"),
          C = [];
        h.id = "atvImg__" + u, m.className = "atvImg-container", f.className = "atvImg-shine", g.className = "atvImg-shadow", k.className = "atvImg-layers";
        for (var E = 0; p > E; E++) {
          var y = i.createElement("div"),
            S = v[E].getAttribute("data-img");
          y.className = "atvImg-rendered-layer", y.setAttribute("data-layer", E), y.style.backgroundImage = "url(" + S + ")", k.appendChild(y), C.push(y)
        }
        m.appendChild(g), m.appendChild(k), m.appendChild(f), h.appendChild(m);
        var I = h.clientWidth || h.offsetWidth || h.scrollWidth;
        h.style.transform = "perspective(" + 3 * I + "px)", d ? (s.preventScroll = !1, function(i, a, o, r) {
          h.addEventListener("touchmove", function(t) {
            s.preventScroll && t.preventDefault(), e(t, !0, i, a, o, r)
          }), h.addEventListener("touchstart", function(e) {
            s.preventScroll = !0, t(e, i)
          }), h.addEventListener("touchend", function(e) {
            s.preventScroll = !1, n(e, i, a, o, r)
          })
        }(h, C, p, f)) : ! function(i, a, o, r) {
          h.addEventListener("mousemove", function(t) {
            e(t, !1, i, a, o, r)
          }), h.addEventListener("mouseenter", function(e) {
            t(e, i)
          }), h.addEventListener("mouseleave", function(e) {
            n(e, i, a, o, r)
          })
        }(h, C, p, f)
      }
    }
}
var deviceIsAndroid = navigator.userAgent.indexOf("Android") > 0,
  deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent),
  deviceIsIOS4 = deviceIsIOS && /OS 4_\d(_\d)?/.test(navigator.userAgent),
  deviceIsIOSWithBadTarget = deviceIsIOS && /OS ([6-9]|\d{2})_\d/.test(navigator.userAgent);
FastClick.prototype.needsClick = function(e) {
  switch (e.nodeName.toLowerCase()) {
    case "button":
    case "select":
    case "textarea":
      if (e.disabled) return !0;
      break;
    case "input":
      if (deviceIsIOS && "file" === e.type || e.disabled) return !0;
      break;
    case "label":
    case "video":
      return !0
  }
  return /\bneedsclick\b/.test(e.className)
}, FastClick.prototype.needsFocus = function(e) {
  switch (e.nodeName.toLowerCase()) {
    case "textarea":
      return !0;
    case "select":
      return !deviceIsAndroid;
    case "input":
      switch (e.type) {
        case "button":
        case "checkbox":
        case "file":
        case "image":
        case "radio":
        case "submit":
          return !1
      }
      return !e.disabled && !e.readOnly;
    default:
      return /\bneedsfocus\b/.test(e.className)
  }
}, FastClick.prototype.sendClick = function(e, t) {
  var n, i;
  document.activeElement && document.activeElement !== e && document.activeElement.blur(), i = t.changedTouches[0], n = document.createEvent("MouseEvents"), n.initMouseEvent(this.determineEventType(e), !0, !0, window, 1, i.screenX, i.screenY, i.clientX, i.clientY, !1, !1, !1, !1, 0, null), n.forwardedTouchEvent = !0, e.dispatchEvent(n)
}, FastClick.prototype.determineEventType = function(e) {
  return deviceIsAndroid && "select" === e.tagName.toLowerCase() ? "mousedown" : "click"
}, FastClick.prototype.focus = function(e) {
  var t;
  deviceIsIOS && e.setSelectionRange && 0 !== e.type.indexOf("date") && "time" !== e.type ? (t = e.value.length, e.setSelectionRange(t, t)) : e.focus()
}, FastClick.prototype.updateScrollParent = function(e) {
  var t, n;
  if (t = e.fastClickScrollParent, !t || !t.contains(e)) {
    n = e;
    do {
      if (n.scrollHeight > n.offsetHeight) {
        t = n, e.fastClickScrollParent = n;
        break
      }
      n = n.parentElement
    } while (n)
  }
  t && (t.fastClickLastScrollTop = t.scrollTop)
}, FastClick.prototype.getTargetElementFromEventTarget = function(e) {
  return e.nodeType === Node.TEXT_NODE ? e.parentNode : e
}, FastClick.prototype.onTouchStart = function(e) {
  var t, n, i;
  if (e.targetTouches.length > 1) return !0;
  if (t = this.getTargetElementFromEventTarget(e.target), n = e.targetTouches[0], deviceIsIOS) {
    if (i = window.getSelection(), i.rangeCount && !i.isCollapsed) return !0;
    if (!deviceIsIOS4) {
      if (n.identifier === this.lastTouchIdentifier) return e.preventDefault(), !1;
      this.lastTouchIdentifier = n.identifier, this.updateScrollParent(t)
    }
  }
  return this.trackingClick = !0, this.trackingClickStart = e.timeStamp, this.targetElement = t, this.touchStartX = n.pageX, this.touchStartY = n.pageY, e.timeStamp - this.lastClickTime < this.tapDelay && e.preventDefault(), !0
}, FastClick.prototype.touchHasMoved = function(e) {
  var t = e.changedTouches[0],
    n = this.touchBoundary;
  return Math.abs(t.pageX - this.touchStartX) > n || Math.abs(t.pageY - this.touchStartY) > n ? !0 : !1
}, FastClick.prototype.onTouchMove = function(e) {
  return this.trackingClick ? ((this.targetElement !== this.getTargetElementFromEventTarget(e.target) || this.touchHasMoved(e)) && (this.trackingClick = !1, this.targetElement = null), !0) : !0
}, FastClick.prototype.findControl = function(e) {
  return void 0 !== e.control ? e.control : e.htmlFor ? document.getElementById(e.htmlFor) : e.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")
}, FastClick.prototype.onTouchEnd = function(e) {
  var t, n, i, a, o, r = this.targetElement;
  if (!this.trackingClick) return !0;
  if (e.timeStamp - this.lastClickTime < this.tapDelay) return this.cancelNextClick = !0, !0;
  if (this.cancelNextClick = !1, this.lastClickTime = e.timeStamp, n = this.trackingClickStart, this.trackingClick = !1, this.trackingClickStart = 0, deviceIsIOSWithBadTarget && (o = e.changedTouches[0], r = document.elementFromPoint(o.pageX - window.pageXOffset, o.pageY - window.pageYOffset) || r, r.fastClickScrollParent = this.targetElement.fastClickScrollParent), i = r.tagName.toLowerCase(), "label" === i) {
    if (t = this.findControl(r)) {
      if (this.focus(r), deviceIsAndroid) return !1;
      r = t
    }
  } else if (this.needsFocus(r)) return e.timeStamp - n > 100 || deviceIsIOS && window.top !== window && "input" === i ? (this.targetElement = null, !1) : (this.focus(r), this.sendClick(r, e), deviceIsIOS4 && "select" === i || (this.targetElement = null, e.preventDefault()), !1);
  return deviceIsIOS && !deviceIsIOS4 && (a = r.fastClickScrollParent, a && a.fastClickLastScrollTop !== a.scrollTop) ? !0 : (this.needsClick(r) || (e.preventDefault(), this.sendClick(r, e)), !1)
}, FastClick.prototype.onTouchCancel = function() {
  this.trackingClick = !1, this.targetElement = null
}, FastClick.prototype.onMouse = function(e) {
  return this.targetElement ? e.forwardedTouchEvent ? !0 : e.cancelable && (!this.needsClick(this.targetElement) || this.cancelNextClick) ? (e.stopImmediatePropagation ? e.stopImmediatePropagation() : e.propagationStopped = !0, e.stopPropagation(), e.preventDefault(), !1) : !0 : !0
}, FastClick.prototype.onClick = function(e) {
  var t;
  return this.trackingClick ? (this.targetElement = null, this.trackingClick = !1, !0) : "submit" === e.target.type && 0 === e.detail ? !0 : (t = this.onMouse(e), t || (this.targetElement = null), t)
}, FastClick.prototype.destroy = function() {
  var e = this.layer;
  deviceIsAndroid && (e.removeEventListener("mouseover", this.onMouse, !0), e.removeEventListener("mousedown", this.onMouse, !0), e.removeEventListener("mouseup", this.onMouse, !0)), e.removeEventListener("click", this.onClick, !0), e.removeEventListener("touchstart", this.onTouchStart, !1), e.removeEventListener("touchmove", this.onTouchMove, !1), e.removeEventListener("touchend", this.onTouchEnd, !1), e.removeEventListener("touchcancel", this.onTouchCancel, !1)
}, FastClick.notNeeded = function(e) {
  var t, n;
  if ("undefined" == typeof window.ontouchstart) return !0;
  if (n = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [, 0])[1]) {
    if (!deviceIsAndroid) return !0;
    if (t = document.querySelector("meta[name=viewport]")) {
      if (-1 !== t.content.indexOf("user-scalable=no")) return !0;
      if (n > 31 && window.innerWidth <= window.screen.width) return !0
    }
  }
  return "none" === e.style.msTouchAction ? !0 : !1
}, FastClick.attach = function(e, t) {
  return new FastClick(e, t)
}, "undefined" != typeof define && define.amd ? define(function() {
  return FastClick
}) : "undefined" != typeof module && module.exports ? (module.exports = FastClick.attach, module.exports.FastClick = FastClick) : window.FastClick = FastClick, document.addEventListener("touchstart", function() {}, !0), atvImg();
            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console