CSS animation image of leaf (as if blowing in the wind) - css

This was a personal challenge and I'm reasonably happy with the approach I have come up with below but I'd be keen to see if there are any alternative approaches.
I am working on a site where the logo contains a leaf image.
I thought it might be eye-catching to have the leaf appearing to be "wind-blown" to its final logo position.
I wanted to improve on the first (very basic) version of the CSS #keyframes animation I had written:
#keyframes leafanimation {
0% {transform:translate(900px,500px); color:rgba(255,0,0,0);}
80% {transform:translate(0,0); color:rgba(255,0,0,0);}
100% {transform:translate(0,0); color:rgba(255,0,0,1);}
}
.my-logo {
position:absolute;
top:0;
left:0;
height: 40px;
line-height: 40px;
font-size: 36px;
color: rgb(255,0,0);
animation: leafanimation 6s linear;
}
.my-logo div {
display: inline-block;
width: 20px;
height: 40px;
vertical-align: middle;
background-color: rgb(255,0,0);
border-radius: 20px;
}
<div class="my-logo">
My Logo
<div></div>
</div>

This was the solution I came up with (eventually) using a series of translate and rotate CSS transforms:
#keyframes leafanimation {
0% {transform:translate(900px,500px) rotate(0deg); color:rgba(255,0,0,0);}
20% {transform:translate(850px,450px) rotate(360deg); color:rgba(255,0,0,0);}
40% {transform:translate(450px,200px) rotate(720deg); color:rgba(255,0,0,0);}
60% {transform:translate(100px,100px) rotate(1080deg); color:rgba(255,0,0,0);}
80% {transform:translate(0,0) rotate(1440deg); color:rgba(255,0,0,0);}
100% {transform:translate(0,0) rotate(1440deg); color:rgba(255,0,0,1);}
}
.my-logo {
position:absolute;
top:0;
left:0;
height: 40px;
line-height: 40px;
font-size: 36px;
color: rgb(255,0,0);
animation: leafanimation 6s linear;
}
.my-logo div {
display: inline-block;
width: 20px;
height: 40px;
vertical-align: middle;
background-color: rgb(255,0,0);
border-radius: 20px;
}
<div class="my-logo">
My Logo
<div></div>
</div>

Related

CSS3 Animation: How do I create smooth movement of background image? Seems to be a Chrome only issue

Trying to smoothly animate a div's background image #bg2 over a short pixel distance (while a clip path animates over it). I'm not able to get the image to move smoothly, it jitters and judders. The clip path animation is fine.
I've tried different easing (linear / ease-in-out etc) suggested in another SO thread, and also extending the distance it needs to move, but it still seems to jump pixel by pixel (sort of), rather than move smoothly. (Although, extending the move distance isn't an option in the actual use case).
How can smooth movement of the cat background image #bg2 be accomplished? Thanks.
** Edit: It's totally smooth for me in Firefox, for me it's jittery in Chrome 91.0.4472.114 on Mojave 10.14.6, and less jittery in Safari. For other it seems to be smooth on Chrome also. Hmmm...
var clickTag = "#";
#main-container {
position: absolute;
width: 970px;
height: 250px;
left:-200px;
box-sizing: border-box;
background: #333;
overflow:hidden; perspective: 800px;
border:1px solid #ccc;
}
div, img {
position: absolute;
background-repeat:no-repeat;
width: 970px;
height: 250px;
z-index: 4;
background-size: 970px 250px;
}
#bg2{
width: 970px;
height: 250px;
z-index:2;
background-image:url('https://i.stack.imgur.com/6EcDu.jpg');
-webkit-clip-path: circle(9% at 682px 110px);
clip-path: circle(9% at 682px 110px);
transform: translateY(20px);
background-position: -5px -10px;
}
#bg2{animation: grow 2.5s 2.5s cubic-bezier(0.215, 0.610, 0.355, 1.000) forwards;-webkit-animation: groww 2.5s 2.5s cubic-bezier(0.215, 0.610, 0.355, 1.000) forwards;}
#-webkit-keyframes groww {
0% {opacity:1;transform: translateY(20px);clip-path: circle(9% at 682px 110px);-webkit-clip-path: circle(9% at 682px 110px);background-position: -5px -10px;}
100% {opacity:1;transform: translateY(-4px);clip-path: circle(15% at 682px 128px);-webkit-clip-path: circle(15% at 682px 128px);background-position: 0px 0px;}
}
#keyframes grow {
0% {opacity:1;transform: translateY(20px);clip-path: circle(9% at 682px 110px);background-position: -5px -10px;}
100% {opacity:1;transform: translateY(-4px);clip-path: circle(15% at 682px 128px);background-position: 0px 0px;}
}
<a href="javascript:window.open(window.clickTag)">
<div id="main-container" class="animate">
<div id="bg2"></div>
</div>
</a>
I'm a bit curious about why having a large banner while not displaying it all.
Anyways, I provide another way of animating, basically just changing the height. Hopefully that could give some ideas.
I removed the width to make it slightly more responsive.
The animation somewhat jittery in this solution, but I guess that it depends on your bezier curve. So perhaps that's the issue all along?
var clickTag = "#";
#main-container {
position: relative;
height: 250px;
box-sizing: border-box;
border: 1px solid #ccc;
background-color: #333;
}
#bg2 {
position: absolute;
left: 75%;
top: 50%;
transform: translate(-50%, -50%);
height: 40%;
aspect-ratio: 1;
border-radius: 50%;
background-image: url('https://i.stack.imgur.com/6EcDu.jpg');
background-position: right 25% center;
animation: grow 2.5s 2.5s cubic-bezier(0.215, 0.610, 0.355, 1.000) forwards;
}
#keyframes grow {
to { height: 80%; }
}
<a href="javascript:window.open(window.clickTag)">
<div id="main-container">
<div id="bg2"></div>
</div>
</a>

Smooth Keyframe Animation on Mobile?

I'm working on improving a Keyframe Animation's smoothness. It seems to work perfectly on desktop but is very laggy and not smooth on mobile. How would I need to change my code to make it smooth?
See JSBin: https://jsbin.com/hecifu/6/edit?html,css,js,output
#keyframes overlayAnimation {
0% {
width: 100vw;
height: 100vh;
transform: translate3d(0px, 0px, 0);
background: transparent;
}
25%{
width: 10px;
height: 200px;
transform: translate3d(calc(50vw - 5px), calc(50vh - 100px), 0);
}
50%{
width: 10px;
height: 200px;
transform: translate3d(calc(50vw - 5px), calc(50vh - 100px), 0) rotate(90deg);
}
50.1%{
width: 200px;
height: 10px;
transform: translate3d(calc(50vw - 100px), calc(50vh - 5px), 0) rotate(0deg);
}
75%{
width: 200px;
height: 100vh;
transform: translate3d(calc(50vw - 100px), 0px, 0) rotate(0deg);
}
100%{
width: 100vw;
height: 100vh;
transform: translate3d(0px, 0px, 0) rotate(0deg);
visibility:hidden;
}
There are a few issues that could be causing the slow-down. The main suspect though: remove the box-shadow.
To elaborate
CSS can utilise hardware acceleration for animations... but only for transform and opacity animations - all other animations are run on the CPU, which is less optimised: https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/
Your animation changes the width and height attributes of an element - what you may want to consider is changing it so that the size is altered via a transform: scale(x, y) change instead: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale
But possibly the biggest drain in your animation is actually the box-shadow - you have a box-shadow set that is 2000px in all directions - that is going to be quite a draw on the smartphone, which has to thus calculate (even if it doesn't have to render all of) a box that is at least 4000px larger than the width and height of the device. Box-shadows can be costly to render at the best of times. These documented cases are for scrolling performance, but I should imagine that animating a box-shadow has a similar performance impact.
What might be better here is to try and use a clip-path to clip the content, rather than cover it with a box-shadow. That would work something like this (based on your JSBin):
var $pages = $(".page");
var $overlay = $("#overlay");
$('.page a').on("click", function(){
if($overlay.hasClass("overlayAnimation")) return;
$pages.fadeToggle(4000);
$overlay.addClass("overlayAnimation").on("animationend", function(){
$(this).removeClass("overlayAnimation");
});
});
*{margin:0; box-sizing:border-box;}
html, body{height:100%;}
h1{
font: 60px/2 Helvetica;
color: #fff;
font-weight: normal;
text-align: center;
}
.page{
position: absolute;
overflow: hidden;
width: 90vw;
height: 90vh;
top: 5vh;
left: 5vw;
color: white;
}
#page1{
background: #008562;
}
#page2{
display: none;
background: #ff8600;
}
.page a{
font-family: Helvetica;
color: #fff;
border: 2px solid #fff;
padding: 10px 15px;
display: block;
text-align: center;
margin: 0 auto;
width: 20%;
text-decoration: none;
}
#overlay{
position: fixed;
z-index:999;
width: 100vw;
height: 100vh;
}
#overlay.overlayAnimation{
animation: overlayAnimation 4s forwards;
}
#keyframes overlayAnimation {
0% {
clip-path: inset(0 0);
background: transparent;
}
25%{
clip-path: inset(calc(50% - 100px) calc(50% - 5px));
transform: rotate(0deg);
}
50%{
clip-path: inset(calc(50% - 100px) calc(50% - 5px));
transform: rotate(90deg);
}
50.1%{
clip-path: inset(calc(50% - 5px) calc(50% - 100px));
transform: rotate(0deg);
}
75%{
clip-path: inset(0 calc(50% - 100px));
}
100%{
clip-path: inset(0 0);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="overlay">
<div class="page" id="page1">
<h1>PAGE 1</h1>
Click here
</div>
<div class="page" id="page2">
<h1>PAGE 2</h1>
Click here
</div>
</div>
https://jsbin.com/pojewujoko/edit?html,css,js,output
Maybe give that a go, see if it is any more performant? It's certainly more elegant IMO, and makes more sense to someone viewing the code directly.

How can I animate several elements on the same orbital path in sequence?

I want to create an animation showing a few circles moving one after another in orbit. Currently, I created three circles but they appear on separate lines and thus move in a circular movement, but as a line. How can I change the code to achieve the movement that I want? Here's a codepen with the current status.
Here's the code that I use:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Lato', sans-serif;
font-size: 18px;
line-height: 1.6;
background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
min-height: 100vh;
}
.loader {
height: 50px;
animation: rotate 6s linear infinite;
}
.circle {
display: inline-block;
background-color: purple;
height: 40px;
width: 40px;
border-radius: 50%;
transform: scale(0);
animation: grow 1.5s linear infinite;
margin: -20p;
}
.circle:nth-child(2) {
background-color: palevioletred;
transform: scale(0);
animation-delay: 0.20s;
}
#keyframes rotate {
to {
transform: rotate(360deg)
}
}
#keyframes grow {
50% {
transform: scale(1);
}
}
<div class="loader">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
I'm creating full-size "plates" which I can set to an initial rotation point. The circles end up as pseudo-elements on the plates (to avoid extra markup). Modify the initial rotation values to bring the circles closer together.
.loader {
width: 100px;
height: 100px;
animation: rotate 6s linear infinite;
position: relative;
}
.plate {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.plate:nth-child(2) {
transform: rotate(120deg);
}
.plate:nth-child(3) {
transform: rotate(240deg);
}
.plate:before {
content: '';
position: absolute;
background-color: red;
height: 40px;
width: 40px;
border-radius: 50%;
transform: scale(0);
animation: grow 1.5s linear infinite;
}
.plate:nth-child(2):before {
background: green;
}
.plate:nth-child(3):before {
background: blue;
}
#keyframes rotate {
to {
transform: rotate(360deg);
}
}
#keyframes grow {
50% {
transform: scale(1);
}
}
* {
box-sizing: bordr-box;
margin: 0;
padding: 0;
}
body {
font-family: "Lato", sans-serif;
font-size: 18px;
line-height: 1.6;
background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
min-height: 100vh;
}
<body>
<div class="loader">
<div class="plate"></div>
<div class="plate"></div>
<div class="plate"></div>
</div>
</body>
#isherwood provided a great solution that's easily workable in most modern browsers. But let's say you want more complex motion, like an elliptical orbit.
SVG Animation
You could build the whole thing into an SVG since that supports lots of cool animation while being quite performant. But building SVGs and animating them from scratch is kinda complicated. Luckily, there are tools to help. Here's a few examples: Snapsvg (code library), SVGGator (Web-based animation tool) or Bodymovin (After Effects workflow).
But let's say you want to stick with what can be done in HTML/CSS.
CSS Motion Path
Sadly support is, not great as of Summer 2019 but it will likely be improving. If your audience is using the right browsers (Chrome, Opera, Edge or Chromium based mobile browsers). It's actually pretty easy to use but there are some gotchas. For example, it appears that only the path() property works right now. So you can't use shape keywords like circle() or ellipse() though they're in the spec.
main {
position: relative;
margin: 20px;
}
main,svg {
width: 100px;
height: 100px;
}
path {
stroke-width: 1px;
}
svg {
position:absolute;
opacity: 0.5;
}
#c1 {
stroke: red;
}
#c2 {
stroke: blue;
}
#c3 {
stroke: green;
}
div[class*="c"] {
width: 15px;
height: 15px;
border-radius: 50%;
position: absolute;
box-shadow: 5px 5px 10px 0 rgba(0,0,0,0.3);
}
.c1 {
background-color: red;
offset-path: path('M50,2 C78.2166667,2 98,22.2364005 98,50.5 C98,78.7635995 75.5694444,99 50,99 C24.4305556,99 2,76.5476997 2,50.5 C2,24.4523003 21.7833333,2 50,2 Z');
animation: moveme 5s ease-in-out infinite;
}
.c2 {
background-color: blue;
offset-path: path('M55,13 C80.2774306,13 98,30.9415509 98,56 C98,81.0584491 77.9059606,99 55,99 C32.0940394,99 12,79.0938368 12,56 C12,32.9061632 29.7225694,13 55,13 Z');
animation: moveme 5.25s linear infinite;
}
.c3{
background-color: green;
offset-path: path('M36.0041619,30.5873511 C61.3414991,12.7718541 90.4202796,4.99194919 98.2799065,16.2635432 C106.139533,27.5351371 85.805943,52.9370587 62.845696,69.0811471 C39.885449,85.2252355 7.31148243,93.0730731 1.30061213,84.4528052 C-4.71025818,75.8325372 10.6668246,48.4028481 36.0041619,30.5873511 Z');
animation: moveme 5.5s linear infinite;
}
#keyframes moveme {
100% {
motion-offset: 100%;
offset-distance: 100%;
}
}
<main>
<!-- paths for example -->
<svg viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="orbit" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M50,2 C78.2166667,2 98,22.2364005 98,50.5 C98,78.7635995 75.5694444,99 50,99 C24.4305556,99 2,76.5476997 2,50.5 C2,24.4523003 21.7833333,2 50,2 Z" id="c1"></path>
<path d="M55,13 C80.2774306,13 98,30.9415509 98,56 C98,81.0584491 77.9059606,99 55,99 C32.0940394,99 12,79.0938368 12,56 C12,32.9061632 29.7225694,13 55,13 Z" id="c2"></path>
<path d="M36.0041619,30.5873511 C61.3414991,12.7718541 90.4202796,4.99194919 98.2799065,16.2635432 C106.139533,27.5351371 85.805943,52.9370587 62.845696,69.0811471 C39.885449,85.2252355 7.31148243,93.0730731 1.30061213,84.4528052 C-4.71025818,75.8325372 10.6668246,48.4028481 36.0041619,30.5873511 Z" id="c3"></path>
</g>
</svg>
<div class="c1"></div>
<div class="c2"></div>
<div class="c3"></div>
</main>

Infinitely rolling image using CSS

I would like to have a slowly and repeatedly rolling panoramic image - as if we have a slow rolling drum with the picture pasted on its side. See https://imgur.com/a/AOdQC7T for an animation of such a drum. Ideally I would like to do this in HTML/CSS and my attempt at trying is here:
However, the animation does not wrap around nicely as in the drum animation.
.verticalSpin {
animation: spinVertical 5s linear infinite;
}
.verticalRoll {
animation: rollVertical 5s linear infinite;
}
.verticalRoll:hover, .verticalSpin:hover {
animation-play-state: paused
}
#keyframes spinVertical {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(360deg);
}
}
#keyframes rollVertical {
0% {
margin-left: 100px;
margin-right: -100px;
}
100% {
margin-left: -100px;
margin-right: 100px;
}
}
<div style="text-align: center;">
<div class="verticalRoll">
<img style="width: 100%; max-width: 300px;"
alt="home" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
</div>
<p style="font-family: arial, helvetica, serif; color: blue; border: 1px solid blue; padding: 10px; border-radius: 5px; background-color: lightblue; color: blue;">
Image Animation.
</p>
</div>
Would appreciate any help/pointers to make this happen! Many thanks!!

Making pure css image slider responsive

The following pure css slider is working well, but I need to make it responsive. I've tried replacing the pixel-based sizes with percentages and with vw, but it doesn't line up. I'd be grateful for any ideas.
Here's the html:
<section class="slideshow">
<div class="slideshow-container slide">
<img src="images/anim/home-animation1.jpg" alt="pills">
<img src="images/anim/home-animation2.jpg" alt="scientist">
<img src="images/anim/home-animation3.jpg" alt="chemical structure">
<img src="images/anim/proudmembermassbio.jpg" alt="proud member of MassBio"> </div>
</section>
And the css:
/*general styles*/
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
/* SLIDESHOW STYLES */
.slideshow-container {
width: 1400px; /* the entire "stage" */
font-size: 0;
transition: 1s ease;
height: 315px;
}
.slideshow-container:hover { animation-play-state: paused; }
.slideshow { /* the visible "stage" */
width: 350px;
margin: 1rem auto -1rem;
overflow: hidden;
border: solid 1px white;
}
img, .text-container {
width: 350px;
height: auto;
display: inline-block;
font-size: 16px;
text-align: center;
}
.text-container { /* for text slides */
height: 195px;
position: relative;
}
.slide { animation: slide 10s ease infinite; }
#keyframes slide {
0% { transform: translateX(0%); }
12.5% { transform: translateX(0%); }
25% { transform: translateX(-25%); }
37.5% { transform: translateX(-25%); }
50% { transform: translateX(-50%); }
62.5% { transform: translateX(-50%); }
75% { transform: translateX(-75%); }
87.5% { transform: translateX(-75%); }
99% { transform: translateX(-75%); }
100% { transform: translateX(0); }
}
.p {
margin-top: 140px;
text-align: center;
}
Maybe this is too late for the user that posted this question, but can be helpful for someone else that want a pure responsive CSS slider.
I have created a working example in this CodePen that is working as requested using percentages for widths and in the animation, and for this reason it is responsive and works really well in each resolutions.
All the main solution to have the responsiveness is here:
slider__container {
display: flex;
position: relative;
animation: 30s slide infinite;
font-size: 0;
width: 1000%; /* because I am using 10 slides */
}
The width should be calculated accordingly to how many slides are there in the slider: slides x 100% (slides times 100%, in my example 1000%).

Resources