Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add physics to CSS animations?

Tags:

People also ask

Is CSS good for animation?

CSS allows you to animate HTML elements without JavaScript. It's used to create interesting and eye-catching effects. These include loading animation, hover animation, text animation, background animation, transition animation, and more. Getting attention in a crowded web space is crucial.

Can you have 2 animations in CSS?

While it is true that you cannot play two transform animations at the same time (because one transform would overwrite the other), it is not correct to say "You cannot play two animations since the attribute can be defined only once." See the accepted answer about using comma-separated values with animations.

Which CSS properties Cannot be animated?

you cannot animate the height of an element from an auto-computed, natural height (e.g. an element filled with text), although is is possible to animate its min-height.


I'm just making a loading screen using CSS and I want it to have physically accurate behavior. I'm trying with the animation-timing-function: cubic-bezier(1, 0, 1, 1), looks fine but not as real like I want, at first because I don't know how do cubic-bezier parameters really work, I found this site and just played around with them until I got something nice.

To sum up, how can I add physically accurate behavior to my animation? I am looking for a CSS-only solution, but JavaScript is fine too if it's impossible.

Here you have an example:

body{
    background-color: #02a2bb;
}

.wrapper {
    padding: 50px;
    text-align: center;
}
.content {
    height: 125px;
    margin: 0 auto;
    position: relative;
    display: inline-block;
}
.ball {
    width: 25px;
    height: 25px;
    display: inline-block;
    border-radius: 50%;
    bottom: 0;
    position: relative;
    background-color: #fff;
    z-index: 1;
}
.ball-shadow {
    width: 20px;
    height: 6px;
    border-radius: 50%;
    position: absolute;
    bottom: 9px;
    left: 50%;
    -webkit-transform: translateX(-50%);
    -moz-transform: translateX(-50%);
    transform: translateX(-50%);
}
.animated {
    -webkit-animation-duration: 1s;
    -moz-animation-duration: 1s;
    -ms-animation-duration: 1s;
    -o-animation-duration: 1s;
    animation-duration: 1s;
    -webkit-animation-fill-mode: both;
    -moz-animation-fill-mode: both;
    -ms-animation-fill-mode: both;
    -o-animation-fill-mode: both;
    animation-fill-mode: both;
    -webkit-animation-iteration-count: infinite;
    -moz-animation-iteration-count: infinite;
    -ms-animation-iteration-count: infinite;
    -o-animation-iteration-count: infinite;
    animation-iteration-count: infinite;
}
.animated.jump, .animated.displace, .animated.diffuse-scale {
    -webkit-animation-duration: 3s;
    -moz-animation-duration: 3s;
    -ms-animation-duration: 3s;
    -o-animation-duration: 3s;
    animation-duration: 3s;
}
@-webkit-keyframes jump {
    0% {
        opacity: 1;
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: translate(0, 0);
    }
    15% {
        opacity: 1;
        -webkit-transform: translate(0, 100px) scale(1.1, 0.9);
    }
    30% {
        opacity: 1;
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: translate(0, 15px);
    }
    45% {
        opacity: 1;
        -webkit-transform: translate(0, 100px) scale(1.08, 0.92);
    }
    60% {
        opacity: 1;
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: translate(0, 45px);
    }
    70% {
        opacity: 1;
        -webkit-transform: translate(0, 100px) scale(1.05, 0.95);
    }
    80% {
        opacity: 1;
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: translate(0, 65px);
    }
    85% {
        opacity: 1;
        -webkit-transform: translate(0, 100px) scale(1.03, 0.97);
    }
    90% {
        opacity: 1;
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: translate(0, 80px);
    }
    95% {
        opacity: 1;
        -webkit-transform: translate(0, 100px) scale(1.01, 0.99);
    }
    97% {
        opacity: 1;
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: translate(0, 95px);
    }
    100% {
        opacity: 0;
        -webkit-transform: translate(0, 100px);
    }
}

@keyframes jump {
    0% {
        opacity: 1;
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: translate(0, 0);
        transform: translate(0, 0);
    }
    15% {
        opacity: 1;
        -moz-transform: translate(0, 100px) scale(1.1, 0.9);
        transform: translate(0, 100px) scale(1.1, 0.9);
    }
    30% {
        opacity: 1;
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: translate(0, 15px);
        transform: translate(0, 15px);
    }
    45% {
        opacity: 1;
        -moz-transform: translate(0, 100px)scale(1.08, 0.92);
        transform: translate(0, 100px)scale(1.08, 0.92);
    }
    60% {
        opacity: 1;
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: translate(0, 45px);
        transform: translate(0, 45px);
    }
    70% {
        opacity: 1;
        -moz-transform: translate(0, 100px)scale(1.05, 0.95);
        transform: translate(0, 100px)scale(1.05, 0.95);
    }
    80% {
        opacity: 1;
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: translate(0, 65px);
        transform: translate(0, 65px);
    }
    85% {
        opacity: 1;
        -moz-transform: translate(0, 100px) scale(1.03, 0.97);
        transform: translate(0, 100px) scale(1.03, 0.97);
    }
    90% {
        opacity: 1;
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: translate(0, 80px);
        transform: translate(0, 80px);
    }
    95% {
        opacity: 1;
        -moz-transform: translate(0, 100px) scale(1.01, 0.99);
        transform: translate(0, 100px) scale(1.01, 0.99);
    }
    97% {
        opacity: 1;
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: translate(0, 95px);
        transform: translate(0, 95px);
    }
    100% {
        opacity: 0;
        -moz-transform: translate(0, 100px);
        transform: translate(0, 100px);
    }
}

@-webkit-keyframes diffuse-scale {
    0% {
        box-shadow: 0 14px 8px rgba(0, 0, 0, 0.5);
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: scale(1.5, 1) translateX(-50%);
    }
    15% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -webkit-transform: scale(1, 1) translateX(-50%);
    }
    30% {
        box-shadow: 0 14px 7px rgba(0, 0, 0, 0.5);
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: scale(1.4, 1) translateX(-50%);
    }
    45% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -webkit-transform: scale(1, 1) translateX(-50%);    }
    60% {
        box-shadow: 0 14px 5px rgba(0, 0, 0, 0.5);
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: scale(1.3, 1) translateX(-50%);    }
    70% {
        box-shadow: 0 14 2px rgba(0, 0, 0, 0.5);
        -webkit-transform: scale(1, 1) translateX(-50%);
    }
    80% {
        box-shadow: 0 14px 4px rgba(0, 0, 0, 0.5);
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: scale(1.2, 1) translateX(-50%);
    }
    85% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -webkit-transform: scale(1, 1) translateX(-50%);
    }
    90% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: scale(1.1, 1) translateX(-50%);
    }
    95% {
        box-shadow: 0 14px 3px rgba(0, 0, 0, 0.5);
        -webkit-transform: scale(1, 1) translateX(-50%);
    }
    97% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -webkit-transform: scale(1.05, 1) translateX(-50%);
    }
    100% {
        -webkit-transform: scale(1, 1) translateX(-50%);
    }
}
@keyframes diffuse-scale {
    0% {
        box-shadow: 0 14px 8px rgba(0, 0, 0, 0.5);
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: scale(1.5, 1) translateX(-50%);
        transform: scale(1.5, 1) translateX(-50%);
    }
    15% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -moz-transform: scale(1, 1) translateX(-50%);
        transform: scale(1, 1) translateX(-50%);
    }
    30% {
        box-shadow: 0 14px 7px rgba(0, 0, 0, 0.5);
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: scale(1.4, 1) translateX(-50%);
        transform: scale(1.4, 1) translateX(-50%);
    }
    45% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -moz-transform: scale(1, 1) translateX(-50%);
        transform: scale(1, 1) translateX(-50%);
    }
    60% {
        box-shadow: 0 14px 5px rgba(0, 0, 0, 0.5);
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: scale(1.3, 1) translateX(-50%);
        transform: scale(1.3, 1) translateX(-50%);
    }
    70% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -moz-transform: scale(1, 1) translateX(-50%);
        transform: scale(1, 1) translateX(-50%);
    }
    80% {
        box-shadow: 0 14px 4px rgba(0, 0, 0, 0.5);
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: scale(1.2, 1) translateX(-50%);
        transform: scale(1.2, 1) translateX(-50%);
    }
    85% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -webkit-transform: scale(1, 1) translateX(-50%);
        -moz-transform: scale(1, 1) translateX(-50%);
        transform: scale(1, 1) translateX(-50%);
    }
    90% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: scale(1.1, 1) translateX(-50%);
        transform: scale(1.1, 1) translateX(-50%);
    }
    95% {
        box-shadow: 0 14px 3px rgba(0, 0, 0, 0.5);
        -moz-transform: scale(1, 1) translateX(-50%);
        transform: scale(1, 1) translateX(-50%);
    }
    97% {
        box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
        -moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
        animation-timing-function: cubic-bezier(1, 0, 1, 1);
        -moz-transform: scale(1.05, 1) translateX(-50%);
        transform: scale(1.05, 1) translateX(-50%);
    }
    100% {
        -moz-transform: scale(1, 1) translateX(-50%);
        transform: scale(1, 1) translateX(-50%);
    }
}

@-webkit-keyframes displace {
    from {
        -webkit-animation-timing-function: linear;
        -webkit-transform: translateX(0);
    }
    to {
        -webkit-transform: translateX(100px);
    }
}
@keyframes displace {
    from {
        -moz-animation-timing-function: linear;
        animation-timing-function: linear;
        -moz-transform: translateX(0);
        transform: translateX(0);
    }
    to {
        -moz-transform: translateX(100px);
        transform: translateX(100px);
    }
}
.jump {
    -webkit-animation-name: jump;
    -moz-animation-name: jump;
    -ms-animation-name: jump;
    -o-animation-name: jump;
    animation-name: jump;
}
.diffuse-scale {
    -webkit-animation-name: diffuse-scale;
    -moz-animation-name: diffuse-scale;
    -ms-animation-name: diffuse-scale;
    -o-animation-name: diffuse-scale;
    animation-name: diffuse-scale;
}
.displace {
    -webkit-animation-name: displace;
    -moz-animation-name: displace;
    -ms-animation-name: displace;
    -o-animation-name: displace;
    animation-name: displace;
}
<div class="wrapper">
    <div class="content animated infinite displace">
        <span class="ball animated infinite jump"></span>
        <span class="ball-shadow animated infinite diffuse-scale"></span>
    </div>
</div>

Suggestion

Something like a less or SCSS with constant physical variables that are defined, or values that you can add to the function and sumule the physical behavior may even have already mixins that simulates certain behavior, I do not know something simple and only CSS.