Tworzenie odwracanej książki za pomocą funkcji CSS Regions i przekształceń 3D

Ilmari Heikkinen

No to nadszedł ten dzień. W końcu znudziły Ci się długie zwoje tekstu i szukasz nowego formatu. Coś eleganckiego. Coś kompaktowego. Coś, co zajmuje długie przewijanie, tworzy zgrabne prostokąty i łączy je ze sobą. Ten wynalazek nazywam „książką”.

Dzięki możliwościom regionów CSS (CanIUse, wejdź na chrome://flags i włącz CSS Regions) oraz przekształceń 3D CSS, najnowocześniejsze technologie tworzenia książek są wreszcie dostępne w nowoczesnych przeglądarkach. Wystarczy kilka wierszy JavaScriptu i duża ilość kodu CSS.

Zacznijmy od zdefiniowania struktury naszej książki. Książka składa się ze stron. Boki zawierają treść książki:

<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>

Użyjemy regionów CSS, aby umieścić tekst książki na stronach książki. Ale najpierw potrzebujemy tekstu książki.

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

Teraz, gdy mamy już gotową książkę, zdefiniujmy CSS przepływu. Używam znaku „+” jako symbolu zastępczego prefiksu dostawcy. Zastąp go znakiem -webkit- (w przypadku przeglądarek WebKit), -moz- (Firefoks) itd.:

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

Teraz zawartość zakresu #book-content zostanie umieszczona w elementach div .book-pages. To jednak dość słaba książka. Żeby znaleźć więcej książek, musimy wyruszyć na misję. Nasza podróż doprowadzi przez tęczowy most przekształceń CSS w zegarowe królestwo JavaScriptu. W korytarzach mechanistycznych bajek wyzwolimy potężne magie przejścia i zdobądźmy 3 baśniowe klawisze, które sterują ogólnym interfejsem.

Opiekun tęczowego mostu przekazuje nam wiedzę na temat stylowych selektorów strukturalnych, dzięki czemu możemy przekształcić strukturę książki HTML w postać książki bardziej przypominającą książkę:

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;
}

W ten sposób opracowujemy styl przypominający papier i docieramy do wielkiej bramy królestwa JavaScriptu. Aby przejść przez bramę, musimy zamienić płaską księgę na odpowiednią wielkość. Aby dodać trochę tomu do książki, odsuwamy każdą stronę lekko na osi 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)');
    }
    }
}
})();

Rzucanie magii przejścia, aby zrobić wrażenie na baśniach, nie jest najtrudniejsze z wywołań. Jednak wyniki sprawiają, że strony książki płynnie się animują.

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

Aby strony faktycznie się przewróciły, musimy powiązać zdarzenia z naszą ideą.

(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++;
        }
    };
})();

Dzięki temu zdobyliśmy technologię „książek” i możemy ewakuować nadświatowe kryształowe wieże, pozostawiając ich blask i ogromny ogień jądrowy Achenar, wielkiej niebieskiej gwiazdy nieba. Triumfując, wracamy do domów, wymachując książki nad głowami, w przygotowaniu na nieuchronną serię parad i uroczystości upamiętniających nasz cześć.

Przykład znajdziesz online tutaj. Znajdziesz tam pełne źródło przykładów. Jeśli nie masz w przeglądarce funkcji CSS Regions, przykładowy kod śledzenia będzie prawdopodobnie niezadowalający. W takim przypadku możesz skorzystać z tego przykładu.