DEV Community

Cover image for CSS perspective and opening book as in 3d
Julia Shlykova
Julia Shlykova

Posted on • Edited on • Originally published at hackernoon.com

CSS perspective and opening book as in 3d

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:

Table of contents

  1. CSS Perspective
  2. perspective-origin
  3. transform-style
  4. Book animation

Perspective

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:

Imaginary perspective
When we change 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 from us the less noticeable the change is.

Perspective-origin

perspective-origin: horizontal-position vertical-position determines the position of user’s eyes relative to the transformed elements. By default, this position is centered: perspective-origin: 50% 50%.

Transform-style

transform-style: preserve-3d allows children of the element 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 parent’s element then we won’t see actual 3d-representation:

Book animation

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>
Enter fullscreen mode Exit fullscreen mode

In what follows, I omit insignificant properties for the topic, you can look at them in the original code in the introduction.

We have 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%;
}
Enter fullscreen mode Exit fullscreen mode

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 behave in their own 3d-space:

.book {
  position: relative;
  transform-style: preserve-3d;
}

.book>div {
  position: absolute;
  top: 0;
  left:0;
  transition: transform 2s;
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

To achieve volume we move every page a little to the right and rotate it around 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);
}
Enter fullscreen mode Exit fullscreen mode

Alright, here we change rotation from -10deg to more extreme values to achieve “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.

Top comments (0)