Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

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.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<div>
  <h1>3D Parallax Buttons</h1>

  <p>Observe the 3D effect as you scroll around. The larger the monitor you use, the bigger the effect you'll be able to see.</p>
  <p></p>

<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<p>Observe all the sides of the buttons here as you scroll down.</p>
<p>The effect is noticable but not distracting.</p>
<p>Looks great on iOS and Android devices as well.</p>
<p>The JavaScript won't be a performance hit.</p>
<p>However, having a hundred 3D transformed objects will most likely slow down mobile devices and weaker computers so use them wisely.</p>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
<button>!</button>
  <h2>This title doesn't need JS, just like the &lt;hr&gt;s down below!</h2>
<p>You can use this technique for both inline links and important call to action buttons.</p>
<p>Combining different types also seems to work well:</p>
<button>Fancy Button!</button><br>
<button class="social">
<svg width="17" height="15" xmlns="http://www.w3.org/2000/svg">
 <g>
  <title>Layer 1</title>
  <g id="g2989" transform="matrix(0.0124718 0 0 -0.0124718 27.9323 53.5044)" fill="#00aced">
   <path id="path2991" d="m-1372.63623,4272.02979c-125,-45 -204,-160.99951 -195,-287.99951l3,-49l-50,6c-182,23 -341,101 -476.00024,231.99951l-66,65l-17,-48c-36,-106.99951 -13,-219.99951 62,-295.99951c40,-42 31,-48 -38,-23c-24,8 -45,14 -47,11c-7,-7 17,-98 36,-134c26,-50 79,-99 137.00024,-128l49,-23l-58,-1c-56.00024,0 -58.00024,-1 -52.00024,-22c20,-65 99.00024,-134 187.00024,-164l62,-21l-54,-32c-80,-46 -174.00024,-72 -268.00024,-74c-45,-1 -82,-5 -82,-8c0,-10 122,-66 193.00012,-88c213.00012,-65 466.00012,-37 656.00012,74c135,79 270,236 333,388c34,81 67.99994,229 67.99994,300c0,46 3,52 59,107c33,32 64,66.99951 70,76.99951c10,19 9,19 -42,2c-85,-29.99951 -97,-25.99951 -55,19c31,32 68,90 68,107c0,3 -15,-2 -32,-11c-18,-10 -58,-25 -88,-34l-53.99994,-17l-49,33c-27,18 -65,38 -85,44c-51,14 -129,12 -175,-4z" fill="#000000"/>
  </g>
 </g>
</svg>
</button>
<button class="social">
<svg width="7" height="15" xmlns="http://www.w3.org/2000/svg">
 <title>Facebook Home</title>
 <g>
  <title>Layer 1</title>
  <path id="path3857-4" d="m4.92885,0c-2.49491,0 -3.37211,1.26051 -3.37211,3.37858l0,1.55835l-1.55673,0l0,2.59617l1.55673,0l0,7.5331l3.11185,0l0,-7.5331l2.07726,0l0.27481,-2.59617l-2.35207,0l0.00323,-1.2997c0,-0.67724 0.06482,-1.03944 1.0362,-1.03944l1.29809,0l0,-2.59779l-2.07726,0z" mask="none" fill="#000000"/>
 </g>
</svg>
</button>
<button class="social">
<svg width="15" height="15" xmlns="http://www.w3.org/2000/svg">
   <circle id="svg_4" fill="#000" r="2.05961" cy="12.95838" cx="2.05961"/>
   <path id="svg_5" fill="#000" d="m9.95478,15.01799l-2.91778,0a7.037,7.037 0 0 0 -7.037,-7.037l0,-2.91778a9.95478,9.95478 0 0 1 9.95478,9.95478z"/>
   <path id="svg_6" fill="#000" d="m12.01439,15.01799a12.01439,12.01439 0 0 0 -12.01439,-12.01439l0,-3.0036a15.01799,15.01799 0 0 1 15.01799,15.01799l-3.0036,0z"/>
</svg>
</button>
<hr />
</div>
              
            
!

CSS

              
                @import "compass/css3";

/* button variables */
$bsize: 18px;
$blue: #aad1ee;
$titlefoldsize: 50px;
$animtiming: 80ms steps(20) both;

html {
  height: 100%;
  overflow: hidden;
  background: #777;
}


/* the perspective set here is the most important declaration for the 3d look of the buttons (values over 1000px make the buttons look almost flat) */
body {
  margin: 0;
  height: 100%;
  overflow-y: scroll;
  font-family: sans-serif;
  font-size: 16px;
  perspective: 350px;
}

div {
  width: 600px;
  margin: 0 auto;
  padding: 20px 20px 600px;
  background: #fff;
  transform-style: preserve-3d;
}

h1, h2 {
  text-align: center;
}

h1, h2, hr {
  position: relative;
  background: #444;
  color: #fff;
  line-height: 2em;
  margin-left: -$titlefoldsize;
  margin-right: -$titlefoldsize;
  transform-style: preserve-3d;
  transform: translateZ(1px);
  
  &::before, &::after {
    content:"";
    position: absolute;
    top: 0;
    width: $titlefoldsize;
    height: 100%;
    background: darken(#444, 10%);
  }
    
  &::before {
    left: -$titlefoldsize;
    transform-origin: 100% 0%;
    transform: rotateY(-130deg);
  }
  &::after {
    right: -$titlefoldsize;
    transform-origin: 0% 0%;
    transform: rotateY(130deg);
  }
}

hr {
  border: 0;
  height: 10px;
  background: #444;
}

button {
  position: relative;
  display: inline-block;
  padding: 4px 16px;
  border: 0;
  min-width: 48px;
  margin: 10px;
  font-size: 24px;
  font-weight: bold;
  background-color: $blue;

  background-image: radial-gradient(ellipse at top, rgba(255,255,255,0.15) 50%, transparent);
  color: #222;
  transform-style: preserve-3d;
  transform: translateZ( $bsize );
  cursor: pointer;
  user-select: none;

  &:focus {outline: none;}
  /* double colon syntax for pseudo elements because IE8 doesn't need to see them (no transforms) */
  &::before, &::after {
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    background: darken($blue, 25%);
    transform-origin: 0% 0%;
  }
  &::before {
    content:"";
    height: $bsize;
    background: darken($blue, 15%);
    transform: rotateX(-90deg);
  }
  &::after {
    content:"";
    width: $bsize;
    transform: rotateY(90deg);
  }

  &.top-half::before {
    top: auto;
    bottom: 0;
    background: darken($blue, 35%);
    transform-origin: 100% 100%;
    transform: rotateX(90deg);
  }

  &.left-half::after {
    left: auto;
    right: 0;
    transform-origin: 100% 100%;
    transform: rotateY(-90deg);
  }


/* pushing the button down; done with animations with steps because transitions are too buggy and jumpy */
  &:active {  
    animation: button $animtiming;
    &::before {
      animation: buttonbefore $animtiming;
    }
    &::after {
      animation: buttonafter $animtiming;
    }
  }
}

@keyframes button {
    to { transform: translateZ( $bsize/2 ) }
}
@keyframes buttonbefore {
    to { height: $bsize/2; }
}
@keyframes buttonafter {
    to { width: $bsize/2; }
}


/* hide pseudo elements in IE9 and IE10 (no 3D transforms) */
@media screen and (min-width:0\0) {  
  button::before, button::after {
    display: none;
  }
}

/* hide pseudo elements in non-webkit Opera) */
x:-o-prefocus, button::before, button::after {
  display: none;
}
              
            
!

JS

              
                // changing the sides of the button only on load and on browser resize
$(window).on("load resize", function() {
	topHalf();
	leftHalf();
});

// when scrolling vertically only top and bottom sides need to be recalculated
$("body").scroll(function() {
	topHalf();
});

// toggle button class if it's in the top or bottom half of the screen
function topHalf() {
	$("button").each(function() {
		var self = $(this),
        offTop = self.offset().top,
        scrTop = $(window).scrollTop(),
        halfWindowHeight = ($(window).height())/2;

		self.toggleClass("top-half", (offTop - scrTop) < halfWindowHeight);
	});
}

// toggle button class if it's in left or right half of the screen
function leftHalf() {
	$("button").each(function() {
		var self = $(this),
        offLeft = self.offset().left,
        halfWindowWidth = ($(window).width())/2;

		self.toggleClass("left-half", offLeft < halfWindowWidth);
	});
}
              
            
!
999px

Console