style.scss 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // animation vars
  2. $duration: 0.35s;
  3. $bounce: cubic-bezier(0.375, 1.495, 0.610, 0.780);
  4. // dimensions
  5. $height: 300px;
  6. $width: 200px;
  7. .flipper-card {
  8. box-shadow: 0 10px 5px -5px rgba(#000, 0.2);
  9. height: $height;
  10. left: 50%;
  11. line-height: $height;
  12. margin: -($height / 2) 0 0 -($width / 2);
  13. perspective: 500px;
  14. position: absolute;
  15. text-align: center;
  16. top: 50%;
  17. transform: translateZ(0);
  18. width: $width;
  19. // the basic "card"
  20. // there are four of these: top current, top next, bottom current, and bottom next
  21. span {
  22. background: #202020;
  23. color: #f8f8f8;
  24. display: block;
  25. font-size: 250px;
  26. left: 0;
  27. position: absolute;
  28. top: 0;
  29. 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);
  30. transform-origin: 0 150px 0;
  31. width: 100%;
  32. // the dividing line in the center
  33. &:before {
  34. border-bottom: 2px solid #000;
  35. content: '';
  36. left: 0;
  37. position: absolute;
  38. width: 100%;
  39. }
  40. // a shadow fill that adds some convexity on the card surfaces
  41. &:after {
  42. box-shadow: inset 0 0 60px rgba(#000, 0.35);
  43. content: '';
  44. height: 100%;
  45. left: 0;
  46. position: absolute;
  47. top: 0;
  48. width: 100%;
  49. }
  50. }
  51. // two-digit numbers get the 'small' class
  52. .small {
  53. font-size: 175px;
  54. }
  55. .top {
  56. // top card sit above the bottom ones, so if we give them the same
  57. // border radius they'll create some crunchiness.
  58. // instead, go one pixel smaller
  59. border-top-left-radius: 11px;
  60. border-top-right-radius: 11px;
  61. // creating a light shine on the top of the card
  62. box-shadow: inset 0 2px rgba(#000, 0.9), inset 0 3px 0 rgba(#fff, 0.4);
  63. // top cards are only 50% height, and overflow-hidden
  64. // so they only show the top of their number
  65. height: 50%;
  66. overflow: hidden;
  67. &:before {
  68. bottom: 0;
  69. }
  70. &:after {
  71. // top card needs to get darker as it curves downward
  72. background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
  73. border-top-left-radius: 11px;
  74. border-top-right-radius: 11px;
  75. }
  76. }
  77. .bottom {
  78. // bottom cards are 100% height, but their top half is hidden by "top" cards
  79. // this was the best way I could think of to show the bottom cards in half, but
  80. // there's probably another way using display: table-cell and vertical-align.
  81. // ew.
  82. border-radius: 10px;
  83. height: 100%;
  84. &:before {
  85. top: 50%;
  86. }
  87. &:after {
  88. border-radius: 10px;
  89. background: linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0));
  90. }
  91. }
  92. // styles that only apply when counting "down"
  93. &.down {
  94. .top {
  95. // use a higher number than the bottoms to prevent crunchy border radiuses
  96. border-top-left-radius: 11px;
  97. border-top-right-radius: 11px;
  98. height: 50%;
  99. &.current {
  100. // required to prevent safari bug: https://bugs.webkit.org/show_bug.cgi?id=61824
  101. transform-style: flat;
  102. z-index: 3;
  103. }
  104. &.next {
  105. // when counting down, the next top card is rotated towards the user (and invisible)
  106. transform: rotate3d(1, 0, 0, -90deg);
  107. z-index: 4;
  108. }
  109. }
  110. .bottom {
  111. border-radius: 10px;
  112. &.current {
  113. z-index: 2;
  114. }
  115. &.next {
  116. z-index: 1;
  117. }
  118. }
  119. &.changing {
  120. .bottom.current {
  121. box-shadow: 0 75px 5px -20px rgba(#000, 0.3);
  122. transform: rotate3d(1, 0, 0, 90deg);
  123. // the current bottom card rotates up to hide itself, and reveal the next one
  124. transition: transform 0.35s ease-in, box-shadow 0.35s ease-in;
  125. }
  126. }
  127. &.changing,
  128. &.changed {
  129. .top.next {
  130. // and the next top card rotates into view (after $duration)
  131. transition: transform 0.35s ease-out 0.35s;
  132. transform: none;
  133. }
  134. }
  135. }
  136. &.up {
  137. .top {
  138. height: 50%;
  139. &.current {
  140. z-index: 4;
  141. }
  142. &.next {
  143. z-index: 3
  144. }
  145. }
  146. .bottom {
  147. &.current {
  148. z-index: 1;
  149. }
  150. &.next {
  151. box-shadow: 0 75px 5px -20px rgba(#000, 0.3);
  152. // when counting "up", the next bottom card begins pointed at the user...
  153. transform: rotate3d(1, 0, 0, 90deg);
  154. z-index: 2;
  155. }
  156. }
  157. &.changing {
  158. .top.current {
  159. // and the current top card does the rotating
  160. transform: rotate3d(1, 0, 0, -90deg);
  161. // when the card is "dropping" it should be faster
  162. transition: transform 0.2625s ease-in, box-shadow 0.2625s ease-in;
  163. }
  164. }
  165. &.changing,
  166. &.changed {
  167. .bottom.next {
  168. box-shadow: 0 0 0 0 rgba(#000, 0);
  169. // add a little bounce at the moment the card finishes falling
  170. 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;
  171. transform: rotate3d(1, 0, 0, 0);
  172. }
  173. }
  174. }
  175. &.changed {
  176. .top.current,
  177. .bottom.current {
  178. display: none;
  179. }
  180. }
  181. }