A Pen by Amit Sheen on CodePen.
Created
July 1, 2021 02:32
-
-
Save CodeMyUI/e348a262c74d021b8e4b6cb4256042d5 to your computer and use it in GitHub Desktop.
Turning pages with CSS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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="_top"> | |
<img src="https://assets.codepen.io/1948355/twitterLogo2.png" /> | |
</a> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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%); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment