Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <script src="https://rawgithub.com/ai/autoprefixer-rails/master/vendor/autoprefixer.js"></script>
<meta name="description" content="clip-path paralaxed paging scrollers">
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, width=device-width, maximum-scale=1">
  <title>clip-path paralaxed paging scrollers</title>
<style type="unprocessed" id="AutoprefixerIn">%css%</style>
<style id="AutoprefixerOut"></style>
<script>
AutoprefixerSettings = { browsers: ['last 2 versions'] };
document.getElementById("AutoprefixerOut").innerHTML = autoprefixer.process(document.getElementById("AutoprefixerIn").innerHTML, AutoprefixerSettings).css;
</script>
</head>
<body>
<input class="demo" name="type" type="radio">
<label class="label">1/9</label>
<input class="demo" name="type" type="radio">
<label class="label">1/3</label>
<input class="demo" name="type" type="radio" checked>
<label class="label">1/2</label>
<input class="demo" name="type" type="radio">
<label class="label">3/4</label>
<input class="demo" name="type" type="radio">
<label class="label">7/8</label>
<div class="pager pager--overlap">
  <div class="pages">
    <div class="page">
      <div class="page-laxwrap">
        <div class="page-lax">
        </div>
      </div>
      <div class="page-scrollport">
        <div class="page-scrollbox">
          <div class="content">page 1</div>
        </div>
      </div>
    </div>
    <div class="page">
      <div class="page-laxwrap">
        <div class="page-lax">
        </div>
      </div>
      <div class="page-scrollport">
        <div class="page-scrollbox">
          <div class="content">page 2</div>
        </div>
      </div>
    </div>
    <div class="page">
      <div class="page-laxwrap">
        <div class="page-lax">
        </div>
      </div>
      <div class="page-scrollport">
        <div class="page-scrollbox">
          <div class="content">page 3</div>
        </div>
      </div>
    </div>
    <div class="page">
      <div class="page-laxwrap">
        <div class="page-lax">
        </div>
      </div>
      <div class="page-scrollport">
        <div class="page-scrollbox">
          <div class="content">page 4</div>
        </div>
      </div>
    </div>
  </div>
</div>
</body>
</html>
 
@import url('https://necolas.github.io/normalize.css/7.0.0/normalize.css');
:root {
  --viewportHeight: 100vh;
  --pageHeight: var(--viewportHeight);
  --pageWidth: 100vw;
  /* flex row isn't causing the layout so need to hard set based upon page amount */
  --pageAmount: 4;
  /* 0 - infinite */
  /* 0 = fixed, infinite = scrollMove, 1 = halfScroll */
  --mag: 1;
  /* this is half gap in use */
  --gap: 1rem;
}
*,
*::before,
*::after {
  box-sizing: inherit;
  -webkit-flex-shrink: 0;
  flex-shrink: 0;
}
html {
  box-sizing: border-box;
}
html,
body {
  overflow: hidden;
  overscroll-behavior: none;
  
  font-weight: bold;
}
.pager {
  --bottomScrollOffset: 50px;
  position: fixed;
  z-index: 1;
  top: 0;
  left: calc(-1 * var(--pageWidth));
  right: calc(-1 * var(--pageWidth));
  height: calc(var(--pageHeight) + var(--bottomScrollOffset));
  overflow-x: scroll;
  overflow-y: hidden;
  overscroll-behavior: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
}
.pages {
  height: var(--pageHeight);
  position: relative;
  display: flex;
  align-items: stretch;
  justify-content: start;
  /* force start for chrome */
  scroll-snap-align: start;
  
  padding-left: var(--pageWidth);
}
.page {
  height: var(--pageHeight);
  width: var(--pageWidth);
  position: relative;
  z-index: 1;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  clip-path:
    polygon(
      0% 0%,
      100% 0%,
      100% 100%,
      0% 100%);
  clip-path: inset(0);
  clip-path: padding-box;
  border-radius: calc(2 * var(--gap));
  border: var(--gap) solid transparent;
}
.page-laxwrap {
  pointer-events: none;
  visibility: hidden;
  position: absolute;
  z-index: 1;
  top: calc(-1 * var(--gap));
  left: calc(-1 * (var(--pageWidth) + var(--gap)));
  width: calc(3 * var(--pageWidth));
  height: var(--pageHeight);
  perspective: 1px;
}
.page:last-child .page-laxwrap {
  margin-right: calc(-3 * var(--pageWidth));
}
.page-lax {
  visibility: visible;
  width: calc(1 * var(--pageWidth));
  height: var(--pageHeight);
  position: sticky;
  left: calc(1 * var(--pageWidth));
  
  transform-origin: center center;
  transform: translateZ(-4px) scale(5);
  transform: translateZ(-.5px) scale(1.5);
  transform: translateZ(-1px) scale(2);
  transform: translateZ(-.25px) scale(1.25);
  
  transform: translateZ(calc(var(--mag) * -1px)) scale(calc(var(--mag) + 1));
  
  background-size: cover;
  background-position: center;
}
.page:nth-of-type(1) .page-lax { background-image: url('//placekitten.com/992/1208'); }
.page:nth-of-type(2) .page-lax { background-image: url('//placekitten.com/901/1202'); }
.page:nth-of-type(3) .page-lax { background-image: url('//placekitten.com/952/1201'); }
.page:nth-of-type(4) .page-lax { background-image: url('//placekitten.com/802/1302'); }
.pages {
  width: calc(var(--pageWidth) * (1 + var(--pageAmount)));
}
.page-scrollport {
  position: absolute;
  z-index: 2;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  overflow-y: scroll;
  overflow-x: hidden;
  overscroll-behavior: auto contain;
  -webkit-overflow-scrolling: touch;
  
  color: #fff;
}
.page-scrollbox {
  min-height: calc(var(--pageHeight) * 1.2);
  
  -border: .5rem solid rgba(255,0,0,.325);
}
.content {
  /* skin */
  height: var(--pageHeight);
  display: flex;
  flex-flow: column;
  align-items: center;
  justify-content: center;
}
/* DEMO STUFFS */
.demo:nth-of-type(1):checked ~ .pager { --mag: .125; }
.demo:nth-of-type(2):checked ~ .pager { --mag: .5; }
.demo:nth-of-type(3):checked ~ .pager { --mag: 1; }
.demo:nth-of-type(4):checked ~ .pager { --mag: 3; }
.demo:nth-of-type(5):checked ~ .pager { --mag: 7; }
/*2 = 2/3 */
/*3 = 3/4 */
/*4 = 4/5 */
.label,
.demo {
  position: fixed;
  top: 2rem;
  left: 2rem;
  z-index: 2;
  color: #fff;
}
.label { left: 3.5rem;}
.demo:nth-of-type(2),.label:nth-of-type(2) {top: 3.5rem; }
.demo:nth-of-type(3),.label:nth-of-type(3) {top: 5rem; }
.demo:nth-of-type(4),.label:nth-of-type(4) {top: 6.5rem; }
.demo:nth-of-type(5),.label:nth-of-type(5) {top: 8rem; }
 
function setHeight() {
  var HTML = document.documentElement;
  var heightEl = document.createElement('div');
  heightEl.style.visibility = 'hidden';
  heightEl.style.position = 'absolute';
  heightEl.style.height = '100vh';
  HTML.appendChild(heightEl);
  var heightElHeight = window.getComputedStyle(heightEl).height;
  var ratioHeight = window.innerHeight / parseInt(heightElHeight,10);
  if (ratioHeight !== 1) {
    var newHeight = (ratioHeight * 100) + 'vh';
    HTML.style.setProperty('--viewportHeight', newHeight);
  }
  HTML.removeChild(heightEl);
}
document.addEventListener('DOMContentLoaded', function() {
  setHeight();
  
  
    // cause re-layout of pages to analyze scroll end boundary correctly, because transform makes it think its bigger than it is :(
  var pages = document.querySelector('.pages .page:last-child');
  pages.style.width = '0px';
  setTimeout(function(){
    
    pages.style.width = '';
  },100);
});
window.addEventListener("orientationchange", function() {
  setHeight();
});
Output 300px

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
jonjohnjohnsonpro
0viewers