DEV Community

Cover image for Making Miniature Book with CSS
hashrock
hashrock

Posted on

Making Miniature Book with CSS

Alt Text

As a front-end exercise, I've made a habit of making UI components every Friday.

You can see some of the components I've made in the past in the tag #金曜GUI.

I like small, cute things like miniatures, and yesterday I made a Miniature Book component with CSS and Vue.js.

1. Place some divs at absolute

Alt Text

2. Adding a three-dimensional page with perspective properties

Alt Text

To rotate the div in 3D, use the perspective and transform-style properties.

wrapper:

 perspective: 300px; transform-style: preserve-3d; 

item:

 transform-origin: left center; transform: rotateY(30deg); 

You can use transform-origin and position: absolute to adjust the position.

Alt Text

3. Curve the edges of the page

Alt Text

CSS can be used to create joint animations. I learned this from s14garnet.

Alt Text

Transformations are affected by the parent element. they can be concatenated using preserve-3d.

4. Add dragging interactions to continuously turn pages

Alt Text

The implementation of drag interaction is straightforward: just keep track of the difference in offsetX and reflect it in the rotation angle.

You can use modulo to loop the book, but note that JavaScript modulo can return a negative value.

HTML:

<div id="app" @pointerdown="down" @pointermove="move" @pointerup="up"> ... </div> 

JavaScript:

Number.prototype.mod = function (n) { return ((this % n) + n) % n; }; new Vue({ el: "#app", data: { rotateRaw: 40, rotateOld: 0, offset: null }, methods: { down(ev) { this.$el.setPointerCapture(ev.pointerId); this.offset = ev.offsetX; this.rotateOld = this.rotate; }, up(ev) { this.offset = null; }, move(ev) { if (this.offset) { this.rotateRaw = this.rotateOld - (ev.offsetX - this.offset); } } }, computed: { rotate() { return this.rotateRaw.mod(180); } } }); 

Note that the pointerdown, pointermove and pointerup events require a polyfill in iOS Safari.

To prevent the div element in the wrapper from being selected by dragging, use pointer-events: none to make the Pointer events transparent.

.wrapper { ... pointer-events: none; user-select: none; } 

Here's DEMO:

https://codepen.io/hashrock/pen/RwrxeKe

Vue.js and input type="range" are your friends

I like to adjust the look and feel of the UI with input type="range". It's a one off UI editor. It's similar to building scaffolding to build a house.

Alt Text

Alt Text

Alt Text

input type="range" is useful, but don't forget to write v-model.number to convert its value to a number.

<input type="range" min=0 max=180 step=1 v-model.number="rotate"> 

Top comments (1)

Collapse
 
mxldevs profile image
MxL Devs

Cute components! I'm impressed how relatively little code and is required to implement and even customize it