If you read about 3d in CSS and didn’t fully understand how to make 3d in the way you want using plain CSS, I hope this mini article can be of help. In the end, you will be able to build something like this :)
What is perspective
in CSS? When we set perspective
for the element, it tells the browser that a child of this element should behave as though they are in 3D space.
Amount of perspective determines the distance between user and z=0 plane.
I tried to figure out how it can be that the more perspective amount we set, the less perspective we see. It was really confusing for me at first. Unless I draw some schema:
When we change the z coordinate (translateZ()
) for the child, we move the child along this imaginary z-axis toward the user. So the further this z=0 plane is from us, the less noticeable the change is.
perspective-origin: horisontal-position vertical-position
determines the position of the user’s eyes relative to the transformed elements. By default, this position is centered: perspective-origin: 50% 50%
transform-style: preserve-3d
allows children of the element to be positioned in 3D space. And my question was: but isn’t it what perspective for? Actually, no. Transform-style
doesn’t add depth. If there is no perspective in the parent’s element, then we won’t see actual 3d- representation:
transform-style: preserve-3d
just allows children to live in their own 3D space.
Now, let’s do some cool animation 😃.
First of all, our index.html body will look like this:
<div class="container">
<div class="book">
<span class="shadow"></span>
<div class="back"></div>
<div class="cover-end"></div>
<div class="page last">
<button class="btn-tale">Tale begins...</button>
</div>
<div class="page third"></div>
<div class="page second"></div>
<div class="page first"></div>
<div class="cover">
<img src="https://cdn.pixabay.com/photo/2024/03/30/12/44/landscape-8664708_1280.png" alt="">
</div>
</div>
</div>
In what follows, I omit insignificant properties for the topic; you can look at them in the original code in the introduction.
We have a div block for every page since every page will behave differently. Let’s first add perspective
to the container block:
.container {
perspective: 500px;
perspective-origin: 50% 50%;
}
We use default perspective-origin. But I preferred to explicitly set it for better understanding. So, our eyes are at the center of the container and z=0
plane is at 500px distance from us.
At this point, our book block is set on the plane z=0
and doesn’t have any 3d features. Let’s add transform-style
to allow pages to behave in their own 3d-space:
.book {
position: relative;
transform-style: preserve-3d;
}
.book>div {
position: absolute;
top: 0;
left:0;
transition: transform 2s;
}
Now, let’s add actual 3d :)
.cover {
transform: scaleY(1.05) rotateY(-10deg);
}
.page.first {
transform: translateX(2px) rotateY(-10deg);
}
.page.second {
transform: translateX(4px) rotateY(-10deg);
}
.page.third {
transform: translateX(6px) rotateY(-10deg);
}
.page.last {
transform: translateX(8px) rotateY(-10deg);
}
To achieve volume, we move every page a little to the right and rotate it around the y-axis. Now, let’s change the behavior of the book when we hover over it:
.book:hover .cover{
transform: rotateY(-150deg);
}
.book:hover .page.first{
transform: translateX(2px) rotateY(-150deg);
}
.book:hover .page.second{
transform: translateX(4px) rotateY(-130deg);
}
.book:hover .page.third{
transform: translateX(6px) rotateY(-110deg);
}
Alright, here, we change rotation from -10deg
to more extreme values to achieve the “opening effect.” Also, we should save our translateX
, since transform rewrites all its’ previous values.
And… that’s it! I hope you understand now a little more about perspective in CSS 🙂.