Make the page count of a 3D book visible using CSS custom properties

I am currently building a book section for this site and thought it would be cool to show the books in 3D and also to make it visible how many pages a book has. In this article I would like to show you how to use CSS custom properties to adapt the depth of a 3D book showing how many pages the book has.

3D Book in CSS

There are many resources and code examples how to build a 3D Book in CSS. As a starting point I used this.

Here is the HTML for creating the book:

<div class="book">
<div class="book__wrapper">
<img class="book__cover" src="/books/world-wide-waste.jpg" alt="World Wide Waste: How Digital Is Killing Our Planet-and What We Can Do About It by Gerry McGovern "/>
</div>
</div>

And here is the CSS:

.book {
width: 200px;
height: 300px;
margin: 30px;
display: flex;
align-items: center;
justify-content: center;
perspective: 400px;
}

.book__wrapper {
transform: rotateY(-30deg);
position: relative;
transform-style: preserve-3d;
width: 200px;
height: 300px;
transition: transform 1s ease;
}

.book__cover {
position: absolute;
background: #0d47a1aa;
width: 200px;
height: 300px;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
box-shadow: 5px 5px 20px #666;
}

.book__wrapper::before {
content: ' ';
background: #fff;
height: calc(300px - 2 * 3px);
width: 50px;
top: 3px;
position: absolute;
transform: translateX(calc(200px - 50px / 2 - 3px)) rotateY(90deg) translateX(calc(50px / 2))
}

.book__wrapper::after {
content: ' ';
position: absolute;
left: 0;
width: 200px;
height: 300px;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
background: #01060f;
transform: translateZ(-50px);
box-shadow: -10px 0 50px 10px #666;
}

Screenshot of the above demo showing the book World Wide Waste - How Digital Is Killing Our Planet-and What We Can Do About It by Gerry McGovern

Demo: https://jsbin.com/nuzaten/1/edit?html,css,output

Customize via CSS custom properties

This looks already really great, so now enhance this and change the depth of the book based on the pages of the book.

First let's define a range – I decided to increase the depth every 50 pages, starting from 50 pages and ending at 1000 pages.

html {
--page-count: 50;
--page-count-range: clamp(1, calc(var(--page-count) / 50), 20);
--page-width: calc(10px * var(--page-count-range));
}
/* only showing the updated stuff here */
.book__wrapper::before {
width: var(--page-width);
transform: translateX(calc(200px - var(--page-width) / 2 - 3px)) rotateY(90deg) translateX(calc(calc(var(--page-width)) / 2))
}

.book__wrapper::after {
transform: translateZ(calc(var(--page-width) * -1));
}

Let's go through this.

First, we set three CSS custom properties whereas the first one defines the actual page count.

In the second one it is getting interesting. There we use clamp() to define our minimum as 1 (50 pages or fewer), our preferred value (page count divided by 50) and a maximum of 20 (1000 pages or more).

In the last property we multiply the range by 10px, so we can use that in our CSS for the transform and width properties that we need to adapt.

If you open the demo you can change the --page-count property to see how the depth changes. And that's it. With some small changes, the depth of the book is now reactive. CSS: What a wonderful language!

That was a fun challenge and can't wait to share my book section where you will see this in action.

Resources

Demo: https://jsbin.com/dozadun/3/edit?html,css,output
Create an animated 3D book in CSS, step by step

Back to top