|
$sqSize: 16px; |
|
$contW: 100%; |
|
$contH: 100%; |
|
$xSpaces: 24; |
|
$ySpaces: 14; |
|
$zSpaces: 19; |
|
$xAngle: 80deg; |
|
$zAngle: 0deg; |
|
$books: 11; |
|
$bookStart: 6; |
|
$trans: 0.25s; |
|
|
|
// font sizing |
|
$fFontSize: $sqSize*0.75; |
|
$rFontSize: $sqSize*1.5; |
|
$cntntFontSize: $sqSize*0.7; |
|
|
|
// non-book colors |
|
$btnColor: #c22; |
|
$shelfColor: #441e12; |
|
|
|
/* Block placement */ |
|
// parameters: x-pos,y-pos,z-pos, width,depth,height, color, is-book |
|
$blocks: |
|
// shelf |
|
(2,1,1, 22,14,1, $shelfColor, false), |
|
(1,14,1, 24,1,18, $shelfColor, false), |
|
(1,1,1, 1,13,18, $shelfColor, false), |
|
(24,1,1, 1,13,18, $shelfColor, false), |
|
(1,1,19, 24,14,1, $shelfColor, false), |
|
// books |
|
(2,3,2, 2,11,14, #c00000, true), |
|
(4,3,2, 2,11,15, #891a21, true), |
|
(6,3,2, 2,10,16, #bf3e22, true), |
|
(8,3,2, 2,10,14, #0e4326, true), |
|
(10,3,2, 2,11,15, #0066cc, true), |
|
(12,3,2, 2,11,16, #0f7b7e, true), |
|
(14,3,2, 2,10,15, #084e6f, true), |
|
(16,3,2, 2,11,16, #0b0823, true), |
|
(18,3,2, 2,10,14, #38103d, true), |
|
(20,3,2, 2,10,15, #443344, true), |
|
(22,3,2, 2,10,16, #666777, true); |
|
|
|
@mixin grid($c, $s) { |
|
$fontS: $s/3; |
|
$xC: #c00; |
|
$yC: #080; |
|
background-image: |
|
repeating-linear-gradient( |
|
180deg, |
|
$c, |
|
$c 1px, |
|
transparent 1px, |
|
transparent $s |
|
), |
|
repeating-linear-gradient( |
|
-90deg, |
|
$c, |
|
$c 1px, |
|
transparent 1px, |
|
transparent $s |
|
); |
|
border-bottom: 1px solid $xC; |
|
border-left: 1px solid $yC; |
|
&::before, &::after { |
|
display: block; |
|
font-size: $fontS; |
|
position: absolute; |
|
text-align: center; |
|
width: $fontS; |
|
height: $fontS; |
|
} |
|
&::before { |
|
color: $yC; |
|
content: "y"; |
|
top: 0; |
|
left: -$fontS; |
|
} |
|
&::after { |
|
color: $xC; |
|
content: "x"; |
|
right: 0; |
|
bottom: -$fontS; |
|
} |
|
} |
|
@mixin placeBlock($x, $y, $z, $w, $d, $h, $c, $isBook) { |
|
display: block; |
|
transform: translate3d( |
|
$sqSize*($x - 1), |
|
$sqSize*(-$y - ($d - 1)), |
|
($sqSize*$z) + ($sqSize*($h - 1)) |
|
); |
|
.block-inner > div { |
|
background-color: $c; |
|
&.top, &.bottom { |
|
width: $sqSize * $w; |
|
height: $sqSize * $d; |
|
} |
|
&.top { |
|
transform: rotateX(-90deg) translateY(-$sqSize*($d - 1)); |
|
} |
|
&.bottom { |
|
transform: rotateX(-90deg) translateY(-$sqSize*($d - 1)) translateZ($sqSize*$h); |
|
} |
|
&.front, &.back, &.left, &.right { |
|
&::before { |
|
background-color: #000; |
|
content: ""; |
|
width: 100%; |
|
height: 100%; |
|
} |
|
} |
|
&.front, &.back { |
|
width: $sqSize * $w; |
|
height: $sqSize * $h; |
|
&::before { |
|
opacity: 0.2; |
|
} |
|
} |
|
&.front { |
|
transform: translateZ($sqSize * ($d - 1)); |
|
} |
|
&.left, &.right { |
|
width: $sqSize * $d; |
|
height: $sqSize * $h; |
|
@if ($isBook == true) { |
|
&::before { |
|
opacity: 0; |
|
} |
|
} |
|
@else { |
|
&::before { |
|
opacity: 0.4; |
|
} |
|
} |
|
} |
|
&.right { |
|
transform: rotateY(-270deg) translate3d($sqSize, 0, $sqSize*($w - $d)); |
|
transform-style: preserve-3d; |
|
@if ($isBook == true) { |
|
background-color: #fff; |
|
&::after { |
|
background-color: $c; |
|
content: attr(data-title); |
|
} |
|
} |
|
} |
|
@if ($isBook == true) { |
|
$pgC: #aaa; |
|
&.top, &.back, &.bottom, { |
|
background: { |
|
color: #fff; |
|
image: repeating-linear-gradient(90deg,transparent, transparent 21%, $pgC 21%, $pgC 25%, transparent 25%, transparent 46%, $pgC 46%, $pgC 50%, transparent 50%); |
|
size: $sqSize $sqSize; |
|
}; |
|
} |
|
} |
|
} |
|
} |
|
:root { |
|
font-size: 20px; |
|
} |
|
*, *::before, *::after { |
|
box-sizing: border-box; |
|
margin: 0; |
|
padding: 0; |
|
} |
|
body, input { |
|
font-family: "Hind", sans-serif; |
|
font-size: 1em; |
|
} |
|
body { |
|
background-color: #ccc; |
|
height: 100vh; |
|
margin: 0; |
|
} |
|
input { |
|
position: absolute; |
|
} |
|
input[type=radio] { |
|
top: -20px; |
|
left: -20px; |
|
&:checked ~ input[type=reset] { |
|
visibility: visible; |
|
} |
|
} |
|
input[type=reset] { |
|
background-color: $btnColor; |
|
border: 0; |
|
border-radius: 0; |
|
color: #fff; |
|
padding: 0.5em 0.75em; |
|
bottom: 5%; |
|
left: 50%; |
|
visibility: hidden; |
|
transform: translateX(-50%); |
|
transition: background-color 0.2s; |
|
-webkit-appearance: none; |
|
appearance: none; |
|
&:hover, &:focus { |
|
background-color: $btnColor + #222; |
|
} |
|
&:active { |
|
background-color: $btnColor - #222; |
|
} |
|
} |
|
.container { |
|
animation: fadeIn $trans $trans linear forwards; |
|
display: flex; |
|
margin: auto; |
|
opacity: 0; |
|
overflow: hidden; |
|
position: absolute; |
|
top: 0; |
|
right: 0; |
|
bottom: 0; |
|
left: 0; |
|
width: $contW; |
|
height: $contH; |
|
perspective: 800px; |
|
transform-style: preserve-3d; |
|
} |
|
.surface { |
|
//@include grid(#888, $sqSize); |
|
display: block; |
|
width: $sqSize * $xSpaces; |
|
height: $sqSize * $ySpaces; |
|
margin: auto; |
|
transform-style: preserve-3d; |
|
transform: translateY($sqSize * $zSpaces/2) rotateX($xAngle) rotateZ($zAngle); |
|
transition: transform $trans; |
|
will-change: transform; |
|
} |
|
.block { |
|
display: none; |
|
transform-style: preserve-3d; |
|
position: absolute; |
|
bottom: 0; |
|
} |
|
.block-inner div { |
|
display: flex; |
|
flex-wrap: wrap; |
|
align-content: flex-start; |
|
position: absolute; |
|
width: $sqSize; |
|
height: $sqSize; |
|
} |
|
.block-inner { |
|
position: relative; |
|
width: $sqSize; |
|
transition: transform $trans linear; |
|
transform-style: preserve-3d; |
|
transform: rotateX(-90deg) translateZ($sqSize); |
|
} |
|
.back { |
|
transform: translateZ(-$sqSize) rotateY(180deg); |
|
} |
|
.left { |
|
transform-origin: center left; |
|
transform: rotateY(270deg) translateX(-$sqSize); |
|
} |
|
.right { |
|
transform-origin: top right; |
|
&::after, div { |
|
top: 0; |
|
left: 0; |
|
transform-origin: 0 50%; |
|
transition: transform $trans $trans linear; |
|
} |
|
&::after { |
|
backface-visibility: hidden; |
|
-webkit-backface-visibility: hidden; |
|
color: #fff; |
|
font-size: $rFontSize; |
|
line-height: $rFontSize; |
|
text-align: center; |
|
padding: 20% 5%; |
|
position: absolute; |
|
width: 100%; |
|
height: 100%; |
|
z-index: 2; |
|
} |
|
div { |
|
width: 100%; |
|
height: 100%; |
|
} |
|
} |
|
.top, .bottom { |
|
transform-origin: top center; |
|
} |
|
.spine, .right::after, .contents h1 { |
|
font: { |
|
family: "Lora", serif; |
|
weight: bold; |
|
}; |
|
-webkit-font-smoothing: antialiased; |
|
} |
|
.spine { |
|
background: transparent; |
|
color: #ccc; |
|
font-size: $fFontSize; |
|
line-height: $fFontSize; |
|
top: 0; |
|
left: 0; |
|
transform: rotate(90deg) translate($sqSize*0.75,-50%); |
|
white-space: nowrap; |
|
width: 0; |
|
height: $sqSize; |
|
} |
|
.cover { |
|
background-color: #fff; |
|
z-index: 1; |
|
} |
|
.contents { |
|
font-size: $cntntFontSize; |
|
padding: $sqSize; |
|
h1 { |
|
font-size: 2em; |
|
} |
|
p { |
|
font-family: "Source Sans Pro", serif; |
|
} |
|
} |
|
|
|
// * Render blocks * |
|
// one block only |
|
@if length(nth($blocks,1)) == 1 { |
|
.b1 { |
|
@include placeBlock( |
|
nth($blocks, 1), |
|
nth($blocks, 2), |
|
nth($blocks, 3), |
|
nth($blocks, 4), |
|
nth($blocks, 5), |
|
nth($blocks, 6), |
|
nth($blocks, 7), |
|
nth($blocks, 8) |
|
); |
|
} |
|
} |
|
// more than one block |
|
@else { |
|
@for $b from 1 through length($blocks) { |
|
.b#{$b} { |
|
@include placeBlock( |
|
nth(nth($blocks, $b), 1), |
|
nth(nth($blocks, $b), 2), |
|
nth(nth($blocks, $b), 3), |
|
nth(nth($blocks, $b), 4), |
|
nth(nth($blocks, $b), 5), |
|
nth(nth($blocks, $b), 6), |
|
nth(nth($blocks, $b), 7), |
|
nth(nth($blocks, $b), 8) |
|
); |
|
} |
|
} |
|
} |
|
|
|
/* Book Viewing */ |
|
label:nth-child(n+#{$bookStart}):nth-child(-n+#{$bookStart + $books}):hover .block-inner { |
|
transform: rotateX(-90deg) translateZ($sqSize*4); |
|
} |
|
@for $i from 1 through $books { |
|
input[type=radio]:nth-child(#{$i}) ~ .surface { |
|
label:nth-child(#{$i + $bookStart - 1}) .block-inner { |
|
animation: returnBook $trans linear; |
|
} |
|
} |
|
input[type=radio]:nth-child(#{$i}):checked ~ .surface { |
|
transform: translate(50% - (0% + ((2/$xSpaces) * 100) * $i),$sqSize * $zSpaces/2) rotateX($xAngle) rotateZ($zAngle); |
|
label:nth-child(#{$i + $bookStart - 1}) .block-inner { |
|
animation: viewBook $trans $trans linear forwards; |
|
&:hover { |
|
.right::after, .cover { |
|
transform: rotateY(-135deg); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
@keyframes fadeIn { |
|
from {opacity: 0;} |
|
to {opacity: 1;} |
|
} |
|
@keyframes viewBook { |
|
from {transform: rotateX(-90deg) translateZ($sqSize*4) rotateY(0);} |
|
50% {transform: rotateX(-90deg) translateZ($sqSize*15) rotateY(0);} |
|
to {transform: rotateX(-90deg) translateZ($sqSize*15) rotateY(-90deg) rotateZ(-90deg + $xAngle) translateZ($sqSize*-5);} |
|
} |
|
@keyframes returnBook { |
|
from {transform: rotateX(-90deg) translateZ($sqSize*15) rotateY(-90deg) rotateZ(-90deg + $xAngle) translateZ($sqSize*-5);} |
|
50% {transform: rotateX(-90deg) translateZ($sqSize*15) rotateY(0);} |
|
to {transform: rotateX(-90deg) translateZ($sqSize) rotateY(0);} |
|
} |