1 // FOUNDATION MOTION UI
\r
5 // 1. Base Transitions
\r
11 // 2. Base Animations
\r
15 // 3. HTML Attributes
\r
18 // - - - - - - - - - - - - - - - - - - - - - - - - -
\r
20 /// @Foundation.settings
\r
22 // Classes to use when triggering in/out animations
\r
27 $motion-class-active: (
\r
28 in: "ng-enter-active",
\r
29 out: "ng-leave-active",
\r
31 $motion-class-stagger: (
\r
32 in: "ng-enter-stagger",
\r
33 out: "ng-leave-stagger",
\r
35 $motion-class-showhide: (
\r
36 in: "ng-hide-remove",
\r
39 $motion-class-showhide-active: (
\r
40 in: "ng-hide-remove-active",
\r
41 out: "ng-hide-add-active",
\r
44 // Set if movement-based transitions should also fade the element in and out
\r
45 $motion-slide-and-fade: false !default;
\r
46 $motion-hinge-and-fade: true !default;
\r
47 $motion-scale-and-fade: true !default;
\r
48 $motion-spin-and-fade: true !default;
\r
50 // Default speed for transitions and animations
\r
51 $motion-duration-default: 500ms !default;
\r
53 // Slow and fast modifiders
\r
54 $motion-duration-slow: 750ms !default;
\r
55 $motion-duration-fast: 250ms !default;
\r
56 $motion-stagger-duration-default: 150ms !default;
\r
57 $motion-stagger-duration-short: 50ms !default;
\r
58 $motion-stagger-duration-long: 300ms !default;
\r
60 // Default timing function for transitions and animations
\r
61 $motion-timing-default: ease !default;
\r
63 // Built-in and custom easing functions
\r
64 // Every item in this map becomes a CSS class
\r
70 easeInOut: ease-in-out,
\r
71 bounceIn: cubic-bezier(0.485, 0.155, 0.240, 1.245),
\r
72 bounceOut: cubic-bezier(0.485, 0.155, 0.515, 0.845),
\r
73 bounceInOut: cubic-bezier(0.760, -0.245, 0.240, 1.245),
\r
76 // Default delay for all transitions and animations
\r
77 $motion-delay-default: 0 !default;
\r
78 // Short and long delay modifiers
\r
79 $motion-delay-short: 300ms !default;
\r
80 $motion-delay-long: 700ms !default;
\r
83 // Looks for a timing function in the list of presets
\r
84 // If none are found, returns the value as-is.
\r
85 @function get-timing($timing) {
\r
86 @if map-has-key($motion-timings, $timing) {
\r
87 @return map-get($motion-timings, $timing);
\r
94 // Applies transition settings common to all mixins
\r
95 @mixin transition-basics(
\r
96 $duration: $motion-duration-default,
\r
97 $timing: $motion-timing-default,
\r
98 $delay: $motion-delay-default
\r
100 transition-duration: $duration;
\r
101 transition-timing-function: get-timing($timing);
\r
102 transition-delay: $delay;
\r
105 // Wraps content in an enter/leave class, chained to the parent selector
\r
106 // Define the initial state of a transition here
\r
107 @mixin transition-start($dir) {
\r
108 $sel1: map-get($motion-class, $dir);
\r
109 $sel2: map-get($motion-class-showhide, $dir);
\r
117 // Wraps content in an enter/leave active class, chained to the matching
\r
118 // enter/leave class, chained to the parent selector
\r
119 // Define the end state of a transition here
\r
120 @mixin transition-end($dir) {
\r
121 $sel1: map-get($motion-class, $dir);
\r
122 $sel1A: map-get($motion-class-active, $dir);
\r
124 $sel2: map-get($motion-class-showhide, $dir);
\r
125 $sel2A: map-get($motion-class-showhide-active, $dir);
\r
127 &.#{$sel1}.#{$sel1A},
\r
128 &.#{$sel2}.#{$sel2A} {
\r
133 @mixin stagger($delay-amount) {
\r
134 transition-delay: $delay-amount;
\r
135 // this is to avoid accidental CSS inheritance
\r
136 transition-duration:0;
\r
140 // 1. Base Transitions
\r
141 // - - - - - - - - - - - - - - - - - - - - - - - - -
\r
147 $fade: $motion-slide-and-fade,
\r
148 $duration: $motion-duration-default,
\r
149 $timing: $motion-timing-default,
\r
150 $delay: $motion-delay-default
\r
152 $slideDirections: (
\r
153 top: translateY(-100%),
\r
154 right: translateX(100%),
\r
155 bottom: translateY(100%),
\r
156 left: translateX(-100%),
\r
162 $start: map-get($slideDirections, $from);
\r
163 $end: translateX(0) translateY(0);
\r
166 $start: translateX(0) translateY(0);
\r
167 $end: map-get($slideDirections, $from);
\r
171 @include transition-start($dir) {
\r
172 @include transition-basics($duration, $timing, $delay);
\r
173 transition-property: transform, opacity;
\r
174 backface-visibility: hidden;
\r
177 @if $fade { opacity: if($dir == in, 0, 1); }
\r
179 @include transition-end($dir) {
\r
182 @if $fade { opacity: if($dir == in, 1, 0); }
\r
191 $duration: $motion-duration-default,
\r
192 $timing: $motion-timing-default,
\r
193 $delay: $motion-delay-default
\r
195 @include transition-start($dir) {
\r
196 @include transition-basics($duration, $timing, $delay);
\r
197 transition-property: opacity;
\r
200 @include transition-end($dir) {
\r
210 $perspective: 2000px,
\r
211 $turn-origin: from-back,
\r
212 $fade: $motion-hinge-and-fade,
\r
213 $duration: $motion-duration-default,
\r
214 $timing: $motion-timing-default,
\r
215 $delay: $motion-delay-default
\r
218 // Rotation directions when hinging from back vs. front
\r
219 $rotationAmount: 90deg;
\r
221 top: rotateX($rotationAmount * -1),
\r
222 right: rotateY($rotationAmount * -1),
\r
223 bottom: rotateX($rotationAmount),
\r
224 left: rotateY($rotationAmount),
\r
227 top: rotateX($rotationAmount),
\r
228 right: rotateY($rotationAmount),
\r
229 bottom: rotateX($rotationAmount * -1),
\r
230 left: rotateY($rotationAmount * -1),
\r
235 @if $turn-origin == from-front {
\r
236 $rotation: map-get($rotationsFrom, $from);
\r
238 @else if $turn-origin == from-back {
\r
239 $rotation: map-get($rotationsBack, $from);
\r
242 @warn "`$turn-origin` must be either `from-back` or `from-front`";
\r
245 // Start and end state
\r
249 $start: perspective($perspective) $rotation;
\r
250 $end: rotate(0deg);
\r
253 $start: rotate(0deg);
\r
254 $end: perspective($perspective) $rotation;
\r
259 @if $axis == edge {
\r
266 @include transition-start($dir) {
\r
267 @include transition-basics($duration, $timing, $delay);
\r
268 transition-property: transform, opacity;
\r
270 transform-origin: $origin;
\r
271 @if $fade { opacity: if($dir == in, 0, 1); }
\r
273 @include transition-end($dir) {
\r
275 @if $fade { opacity: if($dir == in, 1, 0); }
\r
284 $fade: $motion-scale-and-fade,
\r
285 $duration: $motion-duration-default,
\r
286 $timing: $motion-timing-default,
\r
287 $delay: $motion-delay-default
\r
289 @include transition-start($dir) {
\r
290 @include transition-basics($duration, $timing, $delay);
\r
291 transition-property: transform, property;
\r
292 transform: scale($from);
\r
293 @if $fade { opacity: if($dir == in, 0, 1) }
\r
295 @include transition-end($dir) {
\r
296 transform: scale($to);
\r
297 @if $fade { opacity: if($dir == in, 1, 0) }
\r
306 $fade: $motion-spin-and-fade,
\r
307 $duration: $motion-duration-default,
\r
308 $timing: $motion-timing-default,
\r
309 $delay: $motion-delay-default
\r
311 $amount: turn-to-deg($amount);
\r
316 $start: if($ccw, $amount, $amount * -1);
\r
321 $end: if($ccw, $amount * -1, $amount);
\r
324 @include transition-start($dir) {
\r
325 transition-property: transform, opacity;
\r
326 transform: rotate($start);
\r
327 @if $fade { opacity: if($dir == in, 0, 1); }
\r
329 @include transition-end($dir) {
\r
330 transform: rotate($end);
\r
331 @if $fade { opacity: if($dir == in, 1, 0); }
\r
336 // 2. Base Animations
\r
337 // - - - - - - - - - - - - - - - - - - - - - - - - -
\r
341 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% {
\r
342 transform: translateX(7%);
\r
344 5%, 15%, 25%, 35%, 45%, 55%, 65%, 75%, 85%, 95% {
\r
345 transform: translateX(-7%);
\r
347 100% { transform: translateX(0); }
\r
351 @keyframes spin-cw {
\r
352 0% { transform: rotate(0deg); }
\r
353 100% { transform: rotate(360deg); }
\r
356 @keyframes spin-ccw {
\r
357 0% { transform: rotate(0deg); }
\r
358 100% { transform: rotate(-360deg); }
\r
362 @keyframes wiggle {
\r
364 transform: rotate(7deg);
\r
366 35%, 45%, 55%, 65% {
\r
367 transform: rotate(-7deg);
\r
369 0%, 30%, 70%, 100% { transform: rotate(0); }
\r
374 $duration: $motion-duration-default,
\r
375 $timing: $motion-timing-default,
\r
376 $delay: $motion-delay-default,
\r
380 animation-name: $animation;
\r
381 animation-duration: $duration;
\r
382 animation-timing-function: $timing;
\r
384 backface-visibility: hidden;
\r
385 transform: translate3d(0,0,0);
\r
387 @if $delay != null {
\r
388 animation-delay: $delay;
\r
390 @if $iterations != null {
\r
391 animation-iteration-count: $iterations;
\r
394 @if $animation == null {
\r
395 @warn "Please include an animation name";
\r
400 // - - - - - - - - - - - - - - - - - - - - - - - - -
\r
402 @include exports(motion) {
\r
408 .slideInDown { @include slide($from: top); }
\r
409 .slideInLeft { @include slide($from: right); }
\r
410 .slideInUp { @include slide($from: bottom); }
\r
411 .slideInRight { @include slide($from: left); }
\r
412 .slideOutBottom { @include slide($dir: out, $from: bottom); }
\r
413 .slideOutRight { @include slide($dir: out, $from: right); }
\r
414 .slideOutUp { @include slide($dir: out, $from: top); }
\r
415 .slideOutLeft { @include slide($dir: out, $from: left); }
\r
418 .fadeIn { @include fade(in, 0, 1); }
\r
419 .fadeOut { @include fade(out, 1, 0); }
\r
422 .hingeInFromTop { @include hinge($dir: in, $from: top); }
\r
423 .hingeInFromRight { @include hinge($dir: in, $from: right); }
\r
424 .hingeInFromBottom { @include hinge($dir: in, $from: bottom); }
\r
425 .hingeInFromLeft { @include hinge($dir: in, $from: left); }
\r
426 .hingeInFromMiddleX { @include hinge($dir: in, $from: top, $axis: center); }
\r
427 .hingeInFromMiddleY { @include hinge($dir: in, $from: right, $axis: center); }
\r
428 .hingeOutFromTop { @include hinge($dir: out, $from: top); }
\r
429 .hingeOutFromRight { @include hinge($dir: out, $from: right); }
\r
430 .hingeOutFromBottom { @include hinge($dir: out, $from: bottom); }
\r
431 .hingeOutFromLeft { @include hinge($dir: out, $from: left); }
\r
432 .hingeOutFromMiddleX { @include hinge($dir: out, $from: top, $axis: center); }
\r
433 .hingeOutFromMiddleY { @include hinge($dir: out, $from: right, $axis: center); }
\r
436 .zoomIn { @include scale(in, 1.5, 1); }
\r
437 .zoomOut { @include scale(out, 0.5, 1); }
\r
440 .spinIn { @include spin(in, 0.75turn); }
\r
441 .spinOut { @include spin(out, 0.75turn); }
\r
442 .spinInCCW { @include spin(in, 0.75turn, true); }
\r
443 .spinOutCCW { @include spin(out, 0.75turn, true); }
\r
446 Transition modifiers
\r
450 .slow { transition-duration: $motion-duration-slow !important; }
\r
451 .fast { transition-duration: $motion-duration-fast !important; }
\r
454 @each $easing in map-keys($motion-timings) {
\r
456 transition-timing-function: map-get($motion-timings, $easing) !important;
\r
461 .delay { transition-delay: $motion-delay-short !important; }
\r
462 .long-delay { transition-delay: $motion-delay-long !important; }
\r
468 .shake { @include animation(shake); }
\r
469 .spin-cw { @include animation(spin-cw); }
\r
470 .spin-ccw { @include animation(spin-ccw); }
\r
471 .wiggle { @include animation(wiggle); }
\r
474 Animation modifiers
\r
482 &.infinite { animation-iteration-count: infinite; }
\r
485 @each $timing in map-keys($motion-timings) {
\r
487 animation-timing-function: map-get($motion-timings, $timing) !important;
\r
492 &.slow { animation-duration: $motion-duration-slow !important; }
\r
493 &.fast { animation-duration: $motion-duration-fast !important; }
\r
496 &.delay { animation-delay: $motion-delay-short !important; }
\r
497 &.long-delay { animation-delay: $motion-delay-long !important; }
\r
499 .stagger { @include stagger($motion-stagger-duration-default); }
\r
500 .stort-stagger { @include stagger($motion-stagger-duration-default); }
\r
501 .long-stagger { @include stagger($motion-stagger-duration-default); }
\r
504 // View animation classes
\r
505 // - - - - - - - - - - - - - - - - - - - -
\r
507 // Applied to the immediate parent of the animating views
\r
508 .position-absolute {
\r
510 position: relative;
\r
513 // Applied to the animating views
\r
515 &.ng-enter-active, &.ng-leave-active {
\r
516 position: absolute !important;
\r
517 backface-visibility: hidden;
\r
518 -webkit-transform-style: preserve-3d;
\r