Écriture d'un livre inverseur à l'aide de régions CSS et de transformations 3D

Ilmari Heikkinen

Alors, le jour est arrivé. Vous vous ennuyez enfin des longs rouleaux de texte et recherchez un nouveau format. Une touche d'élégance Un format compact. Quelque chose qui prend le long parchemin le découpe en petits rectangles soignés et les relie entre eux. J'appelle cette invention le "livre".

Grâce à la puissance des régions CSS (CanIUse, accédez à chrome://flags et activez les régions CSS) et aux transformations CSS 3D, une technologie de livre de pointe est enfin disponible dans les navigateurs modernes. Il vous suffit de quelques lignes de code JavaScript et de beaucoup de code CSS.

Commençons par définir notre structure de livre. Le livre est composé de pages qui comportent deux côtés. Les côtés contiennent le contenu du livre:

<div class="book">
    <div> <!-- first page -->
    <div> <!-- front cover -->
        # My Fancy Book
    </div>
    <div> <!-- backside of cover -->
        # By Me I. Myself
        ## 2012 Bogus HTML Publishing Ltd
    </div>
    </div>
    <!-- content pages -->
    <div>
    <!-- front side of page -->
    <div class="book-pages"></div>
    <!-- back side of page -->
    <div class="book-pages"></div>
    </div>
    <div>
    <div class="book-pages"></div>
    <div class="book-pages"></div>
    </div>
    <div>
    <div class="book-pages"></div>
    <div class="book-pages"></div>
    </div>
</div>

Nous allons utiliser des régions CSS pour insérer le texte du livre dans les pages du livre. Mais d'abord, nous avons besoin du texte du livre.

<span id="book-content">
    blah blah blah ...
</span>

Maintenant que nous avons écrit notre livre, définissons le flux CSS. J'utilise le caractère + comme espace réservé pour le préfixe du fournisseur. Je le remplace par -webkit- pour les navigateurs WebKit, -moz- pour Firefox, etc. :

#book-content {
    +flow-into: book-text-flow;
}
.book-pages {
    +flow-from: book-text-flow;
}

Le contenu de l'élément "span" #book-content sera maintenant placé dans les divisions .book-pages. Cependant, c'est un livre plutôt médiocre. Pour un livre plus littéraire, nous devons nous lancer dans une quête. Notre parcours vous mènera par-dessus le pont arc-en-ciel des transformations CSS pour vous retrouver dans le royaume de l'horlogerie de JavaScript. Dans les couloirs des mécaniciens Fairylord, nous allons lancer des magies de transition épiques et obtenir les trois légendaires clés qui contrôlent l'interface du monde.

Le gardien du pont arc-en-ciel nous transmet la sagesse d'élégants sélecteurs de structure, qui nous permettent de transformer notre structure de livre HTML en une forme plus ressemblant à un livre:

html {
    width: 100%;
    height: 100%;
}
body {
    /* The entire body is clickable area. Let the visitor know that. */
    cursor: pointer;
    width: 100%;
    height: 100%;
    /* Set the perspective transform for the page so that our book looks 3D. */
    +perspective: 800px;
    /* Use 3D for body, the book itself and the page containers. */
    +transform-style: preserve-3d;
}
.book {
    +transform-style: preserve-3d;
    position: absolute;
}
/* Page containers, contain the two sides of the page as children. */
.book > div {
    +transform-style: preserve-3d;
    position: absolute;
}
/* Both sides of a page. These are flat inside the page container, so no preserve-3d. */
.book > div > div {
    /* Fake some lighting with a gradient. */
    background: +linear-gradient(-45deg, #ffffff 0%, #e5e5e5 100%);
    width: 600px;
    height: 400px;
    overflow: hidden;
    /* Pad the page text a bit. */
    padding: 30px;
    padding-bottom: 80px;
}
/* Front of a page */
.book > div > div:first-child {
    /* The front side of a page should be slightly above the back of the page. */
    +transform: translate3d(0px, 0px, 0.02px);
    /* Add some extra padding for the gutter. */
    padding-left: 40px;
    /* Stylish border in the gutter for visual effect. */
    border-left: 2px solid #000;
}
/* Back of a page */
.book > div > div:last-child {
    /* The back side of a page is flipped. */
    +transform: rotateY(180deg);
    padding-right: 40px;
    border-right: 2px solid #000;
}
/* Front cover of the book */
.book > div:first-child > div:first-child {
    /* The covers have a different color. */
    background: +linear-gradient(-45deg, #8c9ccc 0%, #080f40 100%);
    /* Put a border around the cover to make it cover the pages. */
    border: 2px solid #000;
    /* And center the cover. */
    margin-left: -1px;
    margin-top: -1px;
}
/* Back cover of the book */
.book > div:last-child > div:last-child {
    background: +linear-gradient(-45deg, #8c9ccc 0%, #080f40 100%);
    border: 2px solid #000;
    margin-left: -1px;
    margin-top: -1px;
}

En créant ainsi un style quelque peu en forme de papier pour notre code HTML, nous arrivons aux milliers de milliards de portes du royaume JavaScript. Pour franchir la porte, nous devons transformer notre livre plat en un volume approprié. Pour ajouter du volume au livre, décalez légèrement chaque page sur l'axe Z.

(function() {
var books = document.querySelectorAll('.book');
for (var i = 0; i < books.length; i++) {
    var book = books[i];
    var pages = book.childNodes;
    for (var j = 0; j < pages.length; j++) {
    if (pages[j].tagName == "DIV") {
        setTransform(pages[j], 'translate3d(0px, 0px, ' + (-j) + 'px)');
    }
    }
}
})();

Lancer une magie de transition pour impressionner les Fairylords n'est pas la plus difficile des invocations. Pourtant, grâce aux résultats, les pages de notre livre s'animent plus facilement.

.book > div {
    +transition: 1s ease-in-out;
}

Enfin, pour que les pages se tournent réellement, nous devons lier les événements eux-mêmes à notre cause.

(function(){
    // Get all the pages.
    var pages = document.querySelectorAll('.book > div');
    var currentPage = 0;
    // Go to previous page when clicking on left side of window.
    // Go to the next page when clicking on the right side.
    window.onclick = function(ev) {
        if (ev.clientX < window.innerWidth/2) {
        previousPage();
        } else {
        nextPage();
        }
        ev.preventDefault();
    };
    var previousPage = function() {
        if (currentPage > 0) {
        currentPage--;
            // Rotate the page to closed position and move it to its place in the closed page stack.
        setTransform(pages[currentPage], 'translate3d(0px,0px,' + (-currentPage) + 'px) rotateY(0deg)');
        }
    };
    var nextPage = function() {
        if (currentPage < pages.length) {
            // Rotate the page to open position and move it to its place in the opened stack.
        setTransform(pages[currentPage], 'translate3d(0px,0px,' + currentPage + 'px) rotateY(-150deg)');
        currentPage++;
        }
    };
})();

C'est ainsi que nous avons acquis la technologie du "livre" et que nous pouvons évacuer les tours de cristal de la planète et laisser derrière eux leurs reflets aveugles et les feux nucléaires féroces d'Achenar, la grande étoile bleue du nexus. Nous retournons triomphalement dans nos maisons, dressant nos livres au-dessus de nos têtes, prêts à assister à la cascade inévitable de défilés et de célébrations en notre honneur.

Cliquez ici pour consulter un exemple en ligne et obtenir la source complète des exemples. Si vous n'avez pas de régions CSS dans votre navigateur, l'exemple ne fonctionnera pas. Si tel est le cas, vous pouvez essayer cet exemple à la place.