Niq's OA Resources

Animations

When it comes to animations in CSS, for our purposes, there are two kinds of animation:

Transition Animation

Animation interpolated by the browser between two states.

Keyframe Animation

Animation set by a @keyframes rule.

When it comes to the interactions we have on the websites, we're more likely to use the transition animations, but the keyframes do have their place too.

Transition


The transition animations are frankly easier and simpler for us to take advantage of. When setting up your styles for an element, you basically need to set two 'states', and use the transition property to have the computer smartly animate between the two states.

<div class="box">Hello!</div> <style> /* the class's default stylings + transistion */ .box{ text-align: center; width: fit-content; margin: auto; padding: 1rem; font-size: 2rem; background: #066; transition: all .3s; } /* The hover state of the class's stylings */ .box:hover{ transform: scale(1.4); background: #0cc; } </style>
Hello!

Transition Shorthand

Transition is a shorthand property, containing: transition-delay, transition-duration, transition-property, transition-timing-function.

Not all of these parts of the property are required to work, but two are: transition property, and transition-duration. That's to say, you need to specify the part of an element that is going to be animated, and for how long:

<style> .class{ transition: all .3s; } </style>

Property

This is referring to what is being animated. You can have certain css properties being animated (like margin, color, background, etc), or have any of the CSS changes be animated (all). We typically stick with "all" since it's a good cover-all, but some conditions might change.

property all
property color

You can set multiple properties at one with comma seperation:

<style> .class{ transition: width 2s, height 4s; } </style>

Duration

This is is the speed of the animation (in s or ms). I usually do in s (seconds) since it's more recognizable than milliseconds, but that's personal choice. If you put '.3s', it's going to animated between the two states in .3s. If you make it 5s, it will take 5 seconds to animate between the two states.

Duration .3s
Duration 5s

Delay

(Optional) This is the delay in which the animation starts. The default value is 0. It has to be a time value that comes second (the first time will always be the duration).

<style> .class{ transition: all .3s 2s; } </style>
Delay 0s
Delay 2s

Timing-function

(optional) This is the complicated part. This is a setting to specify the "speed curve" of the animation. There are 5 basic options, and a more complex one, which the inspect element can help with:

  • ease - (default) slow start, then fast, then end slowly
  • linear - same speed from start to end
  • ease-in - slow start
  • ease-out - slow end
  • ease-in-out - slow start and end
  • cubic-bezier(n,n,n,n) - lets you define your own values in a cubic-bezier function
Ease
Linear
Ease-in
Ease-out
Ease-in-out
Cubic-Bezier

This is a CSS function that basically is a 4 point curve to determine the speed of an animation. I can't exactly explain the curves, but you can use the inspect elements to adjust the curves (and the other options have variations that convert to these curves as well you should try).

bounce
in and out back
emphasized
elastic

Analysis

The benefit to this set up is it's dependent on the interactions, and it smoothly interpolates between the two states. It's simple, you set up the transition, and you can set two states.

It doesn't just have to be hover, I use it a lot with javascript to add classes to elements and have the transition animate it (Like the logo in the header on the OA homepage)

<style> .headerLogo { margin-left: -150px; opacity: 0; transition: all 1s; } .scrolledDown .headerLogo { margin-top: 0 !important; margin-left: 0; opacity: 1; } </style> <div class="oaNavbar"> <a href="/" class="headerLogo"><img src="/js/widgets/OAlogo/OA logo dark long.svg"></a> </div> <script> var bottom = 300; $(window).scroll(function(){ if ($(this).scrollTop() > bottom){ $('.oaNavbar').addClass('scrolledDown'); } else{ $('.oaNavbar').removeClass('scrolledDown'); } }); </script>

Of course if you set up variables, you can use those as the values as well, this was you could have animations remove with a media query:

<style> :root{ --aniSpeed: .5s; } @media prefers-reduced-motion{ :root{ --aniSpeed: 0s; } } .button{ transition: all var(--aniSpeed); } .button:hover{ transform: scale(1.1); } </style>

The cons of it are the animation itself can affect how the states interact (like the top of the page example, it rotates on hover, and can rotate out of the hover area, and immediately start to revert).




Keyframes


Keyframe animation requires you set up states of CSS for an element to go through, then using the animation property you apply it to an object.

<style> @keyframes colorChange{ from{color: red;} to{color: blue;} } .object{ animation: colorChange 4s infinite; } </style>
Text color change!

@Keyframes

To set up the animation, you need to use a keyframes rule.

@Keyframes [animation name]

You set up an animation by declaring an animation rule, a name for this animation, and the different steps it takes (or keyframes, as the name implies).

Animation Name

When setting up a keyframes rule, you need to set a name for it by putting it after the '@keyframes' and before the curly brace. It can be any text string you make up, you just have to use that same name when attaching it to an element.

Keyframes/steps

The other part of the keyframes rule are the keyframe(s) themselves, or steps. This is declaring the CSS of an element during a particular part of an animation. You set them up like you would any CSS delcaration, but the selector is a percentage of the animation to a "to" or "from" keyword

<style> @keyframes animation{ from{} to{} 0%{} 16%{} 99%{} } </style>

To get an animation to work, you need at least one keyframe in the keyframes rule. If there is only one, the animation will go from its initial CSS to that keyframe, from the keyframe to its initial CSS, or from its initial state, to that keyframe, and back again:

<style> @keyframes ani1{ 0%{ color: red; } } </style>
From red to base color
<style> @keyframes ani2{ 50%{ color: blue; } } </style>
From base color, to blue, back to base color
<style> @keyframes ani3{ 100%{ color: green; } } </style>
From base color to green

You can use as many keyframes as you want to create some pretty complex animations. (The seasonal OA logos animate with this method See Here)

Animation

The animation CSS property is a shorthand propery for the following properties:

  • animation-name
  • animation-duration
  • animation-delay
  • animation-iteration-count
  • animation-direction
  • animation-timing-function
  • animation-fill-mode

To get any animation from a keyframes rule to work on an element, you need to use the animation-name property and animation-duration property in CSS, either as the shorthand "animation" property, or the two expanded ones.

Animation-name

Pretty self explanitory, this attaches the animation set up in the keyframes rule to the element.

<style> @keyframes animationName{ from{left: 0%;} to{left: 100%;} } .element{ animation: animationName; /*or*/ animation-name: animationName; } </style>

Animation-duration

Of course, the example won't work, since it 0 seconds it's gone through the animation and stopped. You need the animation-duration property to tell the computer how long the animation should work for:

<style> .element{ animation: animationName 4s; /*or*/ animation-name: animationName; animation-duration: 4s; } </style>
AAAHHHH!

Animation-iteration-count

This property says how many times an animation is going to play before it stops. I've actually been using it on all the keyframe animations in this document so far so you can see the animations without them stopping.

The default value is 1, meaning it plays it once and stops, but you can set a int (number) to be the amount of times it repeats, or 'infinite' to make an animation play over and over

<style> .element{ animation: animationName 4s infinite; /*or*/ animation-name: animationName; animation-duration: 4s; animation-iteration-count: infinite; } </style>

Animation-delay

This is a property where you can make an element wait before animating (from when the element loads)

<style> .element{ animation: animationName 4s 6s; /*or*/ animation-name: animationName; animation-duration: 4s; animation-delay: 6s; } </style>
AAAHHHH2!

It's important to note that if you're setting up an animation shorthand property, you the delay has to be the second time measurement after the duration.

Animation-direction

This is which direction the animation is played. By default it plays normal, but you can have it go backwards, forwards then backwards, or the reverse.

  • normal - The animation is played as normal (forwards). This is default
  • reverse - The animation is played in reverse direction (backwards)
  • alternate - The animation is played forwards first, then backwards
  • alternate-reverse - The animation is played backwards first, then forwards
<style> .element{ animation: animationName 4s infinite reverse; /*or*/ animation-name: animationName; animation-duration: 4s; animation-iteration-count: infinite; animation-direction: reverse; } </style>
AAAHHHH!reverse

Animation-timing-function

This is the same as the "timing function" in the transition property. You can set the speed curve of the animation:

  • ease - (default) slow start, then fast, then end slowly
  • linear - same speed from start to end
  • ease-in - slow start
  • ease-out - slow end
  • ease-in-out - slow start and end
  • cubic-bezier(n,n,n,n) - lets you define your own values in a cubic-bezier function
Ease
Linear
Ease-in
Ease-out
Ease-in-out

Animation-fill-mode

This property determines if any of the states set in the animation remain before or after the animation.

By default, if a CSS animation on an item has not started, or after it finishes, and element has its default CSS applied to it. This property can have the first keyframe state before it starts, the last keyframe after it ends, or both.

  • none - Default value. Animation will not apply any styles to the element before or after it is executing
  • forwards - The element will retain the style values that is set by the last keyframe (depends on animation-direction and animation-iteration-count)
  • backwards - The element will get the style values that is set by the first keyframe (depends on animation-direction), and retain this during the animation-delay period
  • both - The animation will follow the rules for both forwards and backwards, extending the animation properties in both directions
<style> @keyframes colorChange{ from{color: red;} to{color: blue;} } .element{ animation: animationName 4s infinite 6s ease forwards; /*or*/ animation-name: animationName; animation-duration: 4s; animation-delay: 6s; animation-timing-function: ease; animation-fill-mode: forwards; } </style>
none
forwards
backwards
both

Animation shorthand property

As you've seen in most the above examples, all these properties can be combined into a shorthand combination, so long as the delay is after the duration:

<style> .element{ animation: animationName 4s 4s forwards; /*or*/ animation-name: animationName; animation-duration: 4s; animation-iteration-count: infinite; animation-delay: 6s; animation-fill-mode: forwards; } </style>

Analysis

The benefit to this set up is control. You can have multiple keyframes that an element animates between, rather than just from one state to the other.

You can also easity control the length and have elements repeat.

<style> @keyframes animationName{ 0%{ margin-left: 0; color: red; } 50%{ margin-left: 50%; background: red; color: white; } 75%{ background: blue; } 100%{ margin-left: 0; } } .element{ animation: animationName 3s 3s; } </style>

The cons are if you use it for interactive states (say having a :hover state have the animation there), the animation will abruptly cut off if it stops being hovered on.

Also, if you set an animation on an element further down that doesn't repeat infinitely, it could animate before its even seen.