CodePen Home Turning pages with CSS

HTML
<h1>Turning pages with CSS by Amit Sheen codepen </h1> <div class="imgLoader"></div> <div class="container"> <h1 class="title"> Turning pages<br>with css </h1> <div class="credit"> * Images loaded randomly from Picsum.photos </div> <div class="book"> <div class="gap"></div> <div class="pages"> <div class="page"></div> <div class="page"></div> <div class="page"></div> <div class="page"></div> <div class="page"></div> <div class="page"></div> </div> <div class="flips"> <div class="flip flip1"> <div class="flip flip2"> <div class="flip flip3"> <div class="flip flip4"> <div class="flip flip5"> <div class="flip flip6"> <div class="flip flip7"></div> </div> </div> </div> </div> </div> </div> </div> </div> </div> <a href="https://twitter.com/amit_sheen" class="twitterLink" target="_blank"> <img src="https://assets.codepen.io/1948355/twitterLogo2.png" /> </a>
SCSS
@import url('https://fonts.googleapis.com/css2?family=Indie+Flower&display=swap'); * { padding: 0; margin: 0 auto; box-sizing: border-box; } body { font-family: 'Indie Flower', cursive; background-color: #eee; color: #555; text-align: center; padding: 4em 0; } $bookAngle: 60deg; $speed: 5s; $borderColor: #555; $images: url('https://picsum.photos/420/300?random=1'), url('https://picsum.photos/420/300?random=2'), url('https://picsum.photos/420/300?random=3'), url('https://picsum.photos/420/300?random=4'), url('https://picsum.photos/420/300?random=5'), url('https://picsum.photos/420/300?random=1'); // Preload to images .imgLoader { position: fixed; animation: preLoad 1s steps(1); width: 1px; height: 1px; @keyframes preLoad { @for $i from 0 through 4 { #{$i * 10}% { background-image: nth($images, ($i + 1)); } } 100% { display: none; } } } .container { position: relative; width: 420px; border: #fff solid 2px; border-radius: 4px; height: 420px; } .title { position: absolute; top: 45px; left: 0; width: 100%; font-size: 2em; font-weight: normal; line-height: 1; } .credit { position: absolute; top: 100%; left: 0; font-size: 0.9em; text-align: left; } .book { position: relative; perspective: 630px; perspective-origin: center 50px; transform: scale(1.2); filter: drop-shadow(0px 10px 5px rgba(0,0,0,0.25)); } .page { width: 210px; height: 300px; background-color: #bbb; position: absolute; top: 0px; right: 50%; transform-origin: 100% 100%; border: solid $borderColor 2px; background-size: 420px 300px; background-position: center; &:nth-child(1) {transform: rotateX($bookAngle) rotateY(3deg); } &:nth-child(2) { transform: rotateX($bookAngle) rotateY(4.5deg); } &:nth-child(3) { transform: rotateX($bookAngle) rotateY(6deg); animation: nextPage $speed*5 infinite $speed*-4.8 steps(1); background-size: 420px 300px; background-position: -2px -2px; } &:nth-child(4) { transform: rotateX($bookAngle) rotateY(177deg); } &:nth-child(5) { transform: rotateX($bookAngle) rotateY(175.5deg); } &:nth-child(6) { transform: rotateX($bookAngle) rotateY(174deg); overflow: hidden; &::after { content: ''; width: 210px; height: 300px; position: absolute; top: 0px; right: 0%; transform-origin: center; transform: rotateY(180deg); animation: nextPage $speed*5 $speed*-4 infinite steps(1); background-size: 420px 300px; background-position: 100% -2px; } } @keyframes nextPage { @for $i from 0 through 4 { #{$i * 20}% { background-image: nth($images, ($i + 1)); } } } } .gap { width: 10px; height: 300px; background: none; transform: rotateX($bookAngle); transform-origin: bottom; position: absolute; top: 0px; left: calc(50% - 5px); &::after { content: ''; position: absolute; bottom: 0; left: 50%; transform: translate(-50%, 50%); background-color: $borderColor; width: 10px; height: 5px; border-radius: 50%; } } .flip { width: 32px; height: 300px; position: absolute; top: 0px; transform-origin: 100% 100%; right: 100%; border: solid $borderColor; border-width: 2px 0px; perspective: 4200px; perspective-origin: center; transform-style: preserve-3d; background-size: 420px 300px; &::after { content: ''; position: absolute; top: 0px; right: 0%; width: 100%; height: 100%; transform-origin: center; background-size: 420px 300px; } &.flip1 { right: 50%; animation: flip1 $speed infinite ease-in-out; border-width: 2px 2px 2px 0; &::after { animation: nextFlip1 $speed*5 $speed*-4 infinite steps(1); } } &:not(.flip1) { right: calc(100% - 2px); top: -2px; transform-origin: right; animation: flip2 $speed ease-in-out infinite; } @for $i from 2 through 7 { &.flip#{$i}::after { animation: nextFlip#{$i} $speed*5 $speed*-4 infinite steps(1); } } &.flip7 { width: 30px; border-width: 2px 0px 2px 2px; &::after { animation: nextFlip7 $speed*5 $speed*-4 infinite steps(1); } } @keyframes flip1 { 0%, 20% { transform: rotateX($bookAngle) rotateY(6deg); } 80%, 100% { transform: rotateX($bookAngle) rotateY(174deg); } } @keyframes flip2 { 0%, 20% { transform: rotateY(0deg) translateY(0px); } 50% { transform: rotateY(-15deg) translateY(0px); } } } @keyframes nextFlip1 { @for $i from 0 through 4 { #{$i * 20}% { background-image: nth($images, ($i + 1)); background-position: -178px -2px; transform: rotateY(0deg); } #{10 + ($i * 20)}% { background-image: nth($images, ($i + 2)); background-position: -210px -2px; transform: rotateY(180deg); } } } @for $i from 2 through 6 { @keyframes nextFlip#{$i} { @for $j from 0 through 4 { #{$j * 20}% { background-image: nth($images, ($j + 1)); background-position: #{-148 + (($i - 2) * 30)}px -2px; transform: rotateY(0deg); } #{((10 + ($j * 20)) + (($i - 1) * 0.5))}% { background-image: nth($images, ($j + 2)); background-position: #{-238 - (($i - 2) * 30)}px -2px; transform: rotateY(180deg); } } } } @keyframes nextFlip7 { @for $i from 0 through 4 { #{$i * 20}% { background-image: nth($images, ($i + 1)); background-position: -2px -2px; transform: rotateY(0deg); } #{13 + ($i * 20)}% { background-image: nth($images, ($i + 2)); background-position: -388px -2px; transform: rotateY(180deg); } } } .twitterLink { position: fixed; bottom: 0.5em; right: 0.5em; & img { width: 2em; filter: grayscale(100%); transition: filter 0.25s; &:hover { filter: grayscale(0%); } } }
JAVASCRIPT
Expand for more options Login