|
@@ -0,0 +1,216 @@
|
|
|
|
+// animation vars
|
|
|
|
+$duration: 0.35s;
|
|
|
|
+$bounce: cubic-bezier(0.375, 1.495, 0.610, 0.780);
|
|
|
|
+
|
|
|
|
+// dimensions
|
|
|
|
+$height: 300px;
|
|
|
|
+$width: 200px;
|
|
|
|
+
|
|
|
|
+.flipper-card {
|
|
|
|
+ box-shadow: 0 10px 5px -5px rgba(#000, 0.2);
|
|
|
|
+ height: $height;
|
|
|
|
+ left: 50%;
|
|
|
|
+ line-height: $height;
|
|
|
|
+ margin: -($height / 2) 0 0 -($width / 2);
|
|
|
|
+ perspective: 500px;
|
|
|
|
+ position: absolute;
|
|
|
|
+ text-align: center;
|
|
|
|
+ top: 50%;
|
|
|
|
+ transform: translateZ(0);
|
|
|
|
+ width: $width;
|
|
|
|
+
|
|
|
|
+ // the basic "card"
|
|
|
|
+ // there are four of these: top current, top next, bottom current, and bottom next
|
|
|
|
+ span {
|
|
|
|
+ background: #202020;
|
|
|
|
+ color: #f8f8f8;
|
|
|
|
+ display: block;
|
|
|
|
+ font-size: 250px;
|
|
|
|
+ left: 0;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 0;
|
|
|
|
+ text-shadow: 0 1px 0 (#000 + 40), 0 2px 0 (#000 + 30), 0 3px 0 (#000 + 20), 0 4px 0 (#000 + 10), 0 5px 0 #000, 0 0 10px rgba(#000, 0.8);
|
|
|
|
+ transform-origin: 0 150px 0;
|
|
|
|
+ width: 100%;
|
|
|
|
+
|
|
|
|
+ // the dividing line in the center
|
|
|
|
+ &:before {
|
|
|
|
+ border-bottom: 2px solid #000;
|
|
|
|
+ content: '';
|
|
|
|
+ left: 0;
|
|
|
|
+ position: absolute;
|
|
|
|
+ width: 100%;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // a shadow fill that adds some convexity on the card surfaces
|
|
|
|
+ &:after {
|
|
|
|
+ box-shadow: inset 0 0 60px rgba(#000, 0.35);
|
|
|
|
+ content: '';
|
|
|
|
+ height: 100%;
|
|
|
|
+ left: 0;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 0;
|
|
|
|
+ width: 100%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // two-digit numbers get the 'small' class
|
|
|
|
+ .small {
|
|
|
|
+ font-size: 175px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .top {
|
|
|
|
+ // top card sit above the bottom ones, so if we give them the same
|
|
|
|
+ // border radius they'll create some crunchiness.
|
|
|
|
+ // instead, go one pixel smaller
|
|
|
|
+ border-top-left-radius: 11px;
|
|
|
|
+ border-top-right-radius: 11px;
|
|
|
|
+
|
|
|
|
+ // creating a light shine on the top of the card
|
|
|
|
+ box-shadow: inset 0 2px rgba(#000, 0.9), inset 0 3px 0 rgba(#fff, 0.4);
|
|
|
|
+
|
|
|
|
+ // top cards are only 50% height, and overflow-hidden
|
|
|
|
+ // so they only show the top of their number
|
|
|
|
+ height: 50%;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+
|
|
|
|
+ &:before {
|
|
|
|
+ bottom: 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &:after {
|
|
|
|
+ // top card needs to get darker as it curves downward
|
|
|
|
+ background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
|
|
|
|
+ border-top-left-radius: 11px;
|
|
|
|
+ border-top-right-radius: 11px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .bottom {
|
|
|
|
+ // bottom cards are 100% height, but their top half is hidden by "top" cards
|
|
|
|
+ // this was the best way I could think of to show the bottom cards in half, but
|
|
|
|
+ // there's probably another way using display: table-cell and vertical-align.
|
|
|
|
+ // ew.
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+ height: 100%;
|
|
|
|
+
|
|
|
|
+ &:before {
|
|
|
|
+ top: 50%;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &:after {
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+ background: linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // styles that only apply when counting "down"
|
|
|
|
+ &.down {
|
|
|
|
+ .top {
|
|
|
|
+ // use a higher number than the bottoms to prevent crunchy border radiuses
|
|
|
|
+ border-top-left-radius: 11px;
|
|
|
|
+ border-top-right-radius: 11px;
|
|
|
|
+ height: 50%;
|
|
|
|
+
|
|
|
|
+ &.current {
|
|
|
|
+ // required to prevent safari bug: https://bugs.webkit.org/show_bug.cgi?id=61824
|
|
|
|
+ transform-style: flat;
|
|
|
|
+ z-index: 3;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.next {
|
|
|
|
+ // when counting down, the next top card is rotated towards the user (and invisible)
|
|
|
|
+ transform: rotate3d(1, 0, 0, -90deg);
|
|
|
|
+ z-index: 4;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .bottom {
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+
|
|
|
|
+ &.current {
|
|
|
|
+ z-index: 2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.next {
|
|
|
|
+ z-index: 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.changing {
|
|
|
|
+ .bottom.current {
|
|
|
|
+ box-shadow: 0 75px 5px -20px rgba(#000, 0.3);
|
|
|
|
+ transform: rotate3d(1, 0, 0, 90deg);
|
|
|
|
+
|
|
|
|
+ // the current bottom card rotates up to hide itself, and reveal the next one
|
|
|
|
+ transition: transform 0.35s ease-in, box-shadow 0.35s ease-in;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.changing,
|
|
|
|
+ &.changed {
|
|
|
|
+ .top.next {
|
|
|
|
+ // and the next top card rotates into view (after $duration)
|
|
|
|
+ transition: transform 0.35s ease-out 0.35s;
|
|
|
|
+ transform: none;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.up {
|
|
|
|
+ .top {
|
|
|
|
+ height: 50%;
|
|
|
|
+
|
|
|
|
+ &.current {
|
|
|
|
+ z-index: 4;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.next {
|
|
|
|
+ z-index: 3
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .bottom {
|
|
|
|
+ &.current {
|
|
|
|
+ z-index: 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.next {
|
|
|
|
+ box-shadow: 0 75px 5px -20px rgba(#000, 0.3);
|
|
|
|
+
|
|
|
|
+ // when counting "up", the next bottom card begins pointed at the user...
|
|
|
|
+ transform: rotate3d(1, 0, 0, 90deg);
|
|
|
|
+ z-index: 2;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.changing {
|
|
|
|
+ .top.current {
|
|
|
|
+ // and the current top card does the rotating
|
|
|
|
+ transform: rotate3d(1, 0, 0, -90deg);
|
|
|
|
+
|
|
|
|
+ // when the card is "dropping" it should be faster
|
|
|
|
+ transition: transform 0.2625s ease-in, box-shadow 0.2625s ease-in;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.changing,
|
|
|
|
+ &.changed {
|
|
|
|
+ .bottom.next {
|
|
|
|
+ box-shadow: 0 0 0 0 rgba(#000, 0);
|
|
|
|
+
|
|
|
|
+ // add a little bounce at the moment the card finishes falling
|
|
|
|
+ transition: box-shadow 0.175s cubic-bezier(0.375, 1.495, 0.61, 0.78) 0.35s, transform 0.35s cubic-bezier(0.375, 1.495, 0.61, 0.78) 0.35s;
|
|
|
|
+ transform: rotate3d(1, 0, 0, 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.changed {
|
|
|
|
+ .top.current,
|
|
|
|
+ .bottom.current {
|
|
|
|
+ display: none;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|