4

Background

I have a CSS3 class that makes an icon swing, like an alarm:

@-webkit-keyframes swing {
  15% {
    -webkit-transform: translateX(5px);
    transform: translateX(5px);
  }
  30% {
    -webkit-transform: translateX(-5px);
    transform: translateX(-5px);
  }
  50% {
    -webkit-transform: translateX(3px);
    transform: translateX(3px);
  }
  65% {
    -webkit-transform: translateX(-3px);
    transform: translateX(-3px);
  }
  80% {
    -webkit-transform: translateX(2px);
    transform: translateX(2px);
  }
  100% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
}
@keyframes swing {
  15% {
    -webkit-transform: translateX(5px);
    transform: translateX(5px);
  }
  30% {
    -webkit-transform: translateX(-5px);
    transform: translateX(-5px);
  }
  50% {
    -webkit-transform: translateX(3px);
    transform: translateX(3px);
  }
  65% {
    -webkit-transform: translateX(-3px);
    transform: translateX(-3px);
  }
  80% {
    -webkit-transform: translateX(2px);
    transform: translateX(2px);
  }
  100% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
}
.swing {
  -webkit-animation: swing 1s ease infinite;
  -moz-animation: swing 1s ease infinite;
  animation: swing 1s ease infinite;
}
<!doctype html>

<html lang="en">

<head>
  <meta charset="utf-8">

  <title>Icon swing</title>
  <meta name="css3 code for icon swinging" content="Icon Swing">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>

<body>
  <i class="material-icons swing">alarm</i>
</body>
</html>

Problem

The animation works fine, and it repeats every second. However, users complain, so I would like to make the animation run every X seconds, where X is a number chosen by the user.

Research

To achieve this I made a search in Stackoverflow, which fixed a similar issue by making the animation last 30 seconds, but by running it in the first 5% seconds.

This is fine if you have a static limit (like I want to run an animation every Y seconds, where Y never changes) but it lacks customization.

Questions

  1. Is it possible to make this animation run every X seconds, where X can change?
  2. If not, how do I change this animation to run during the first 5% seconds as well?
Community
  • 1
  • 1
Flame_Phoenix
  • 16,489
  • 37
  • 131
  • 266
  • 1. Yes, with `javascript` (CSS cannot be dynamic). 2. Come again? `5% seconds`? That doesn't make ***any sense***. Is `100% seconds` equal to *"And they lived happily ever after"*? – tao Feb 10 '17 at 11:28
  • 1
    Since you say the number would be chosen by the user, changing the keyframe settings like in the linked thread may not be a good option for you because you'd have to change the style rules (create/append/delete) whenever the user changes the duration and that in my opinion is kind of tedious. Another option that I can think of involves a timeout which is done after every iteration but I'm not sure how efficient this one is either. I can put together a demo of this if you wish to see it. – Harry Feb 10 '17 at 11:29
  • 1
    If by `5% seconds` you mean `5%` of the total animation duration, of course it can be done. Redefine your animation by repeating the frames you have now for `5%` of total repeat time and pause everything for the rest of `95%`. It's going to be a lot of code, but it will work. Another option is to stop the animation by using a different class and apply/remove it using `javascript`. – tao Feb 10 '17 at 11:35

1 Answers1

1

First of all, because your users can change the time and it's difficult to change your CSS dynamically (but not impossible), I recommend to use javascript for this.

1. Is it possible to make this animation run every X seconds, where X can change?

Yes, with javascript. You can use something like setInterval(animateClock, userTime).

Set an id for your HTML element:

<i id="animated-clock" class="material-icons swing">alarm</i>

Set the number of iterations for the animation from infinite to 1 in your CSS class:

.swing {
    -webkit-animation: swing 1s ease 1;
    -moz-animation: swing 1s ease 1;
    animation: swing 1s ease 1;
}

And then in javascript you can use:

var userPersonalTimer = user.timer; // Get this value from the user settings, depending on your application.

setInterval( function() {
    var clock = document.getElementById('animated-clock');
    var newClock = clock.cloneNode(true);
    clock.parentNode.replaceChild(newClock, clock);
}, userPersonalTimer);

Every X seconds (value stablished by the current user) the HTML element will be replaced by a copy of itself, firing the animation again (removing and adding the class again to the element will not work most of the time).

var userPersonalTimer = 5000; // Get this value from the user settings, depending on your application.

setInterval( function() {
    var clock = document.getElementById('animated-clock');
    var newClock = clock.cloneNode(true);
    clock.parentNode.replaceChild(newClock, clock);
}, userPersonalTimer);
.swing {
  -webkit-animation: swing 1s ease 1;
  -moz-animation: swing 1s ease 1;
  animation: swing 1s ease 1;
}

@-webkit-keyframes swing {
  15% {
    -webkit-transform: translateX(5px);
    transform: translateX(5px);
  }
  30% {
    -webkit-transform: translateX(-5px);
    transform: translateX(-5px);
  }
  50% {
    -webkit-transform: translateX(3px);
    transform: translateX(3px);
  }
  65% {
    -webkit-transform: translateX(-3px);
    transform: translateX(-3px);
  }
  80% {
    -webkit-transform: translateX(2px);
    transform: translateX(2px);
  }
  100% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
}
@keyframes swing {
  15% {
    -webkit-transform: translateX(5px);
    transform: translateX(5px);
  }
  30% {
    -webkit-transform: translateX(-5px);
    transform: translateX(-5px);
  }
  50% {
    -webkit-transform: translateX(3px);
    transform: translateX(3px);
  }
  65% {
    -webkit-transform: translateX(-3px);
    transform: translateX(-3px);
  }
  80% {
    -webkit-transform: translateX(2px);
    transform: translateX(2px);
  }
  100% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
}
<!doctype html>

<html lang="en">

<head>
  <meta charset="utf-8">

  <title>Icon swing</title>
  <meta name="css3 code for icon swinging" content="Icon Swing">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>

<body>
  <i id="animated-clock" class="material-icons swing">alarm</i>
</body>
</html>

2. If not, how do I change this animation to run during the first 5% seconds as well?

It's possible as I said in the previous question, but here is how to make it run during the first 5% of the animation-duration. You only have to calculate the percentages.

.swing {
  -webkit-animation: swing 10s linear infinite;
  -moz-animation: swing 10s linear infinite;
  animation: swing 10s linear infinite;
}

@-webkit-keyframes swing {
  0.75% {
    -webkit-transform: translateX(5px);
    transform: translateX(5px);
  }
  1.5% {
    -webkit-transform: translateX(-5px);
    transform: translateX(-5px);
  }
  2.5% {
    -webkit-transform: translateX(3px);
    transform: translateX(3px);
  }
  3.25% {
    -webkit-transform: translateX(-3px);
    transform: translateX(-3px);
  }
  4% {
    -webkit-transform: translateX(2px);
    transform: translateX(2px);
  }
  5% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
}
@keyframes swing {
  0.75% {
    -webkit-transform: translateX(5px);
    transform: translateX(5px);
  }
  1.5% {
    -webkit-transform: translateX(-5px);
    transform: translateX(-5px);
  }
  2.5% {
    -webkit-transform: translateX(3px);
    transform: translateX(3px);
  }
  3.25% {
    -webkit-transform: translateX(-3px);
    transform: translateX(-3px);
  }
  4% {
    -webkit-transform: translateX(2px);
    transform: translateX(2px);
  }
  5% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
}
<!doctype html>

<html lang="en">

<head>
  <meta charset="utf-8">

  <title>Icon swing</title>
  <meta name="css3 code for icon swinging" content="Icon Swing">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>

<body>
  <i class="material-icons swing">alarm</i>
</body>
</html>
Gerard Reches
  • 3,048
  • 3
  • 28
  • 39
  • How would you do it every Y seconds, where Y is static (using only CSS3)? – Flame_Phoenix Feb 10 '17 at 12:41
  • @Flame_Phoenix That will be a little more complicated, because you should have to tweak your `keyframes` percentages to simulate a delay between repetitions. For example, if your animation takes 1 second to do it entirely and Y is 10, you should change the `animation-duration` to Y, and all your transitions should occur between 0% and 10% in your `keyframes`, nothing will be happening between 10% and 100% in order to simulate the interval. It's not very difficult for this 1s running / 10s interval example, but depending on your values, it can be a little tricky and not easily modifiable. – Gerard Reches Feb 10 '17 at 14:15
  • @Flame_Phoenix I will update my answer to solve the question 2. – Gerard Reches Feb 10 '17 at 14:34
  • Very complete, deserving of kudos++ – Flame_Phoenix Feb 10 '17 at 15:13