Skip to content

Instantly share code, notes, and snippets.

@rohanb10
Last active July 2, 2020 11:12
Show Gist options
  • Save rohanb10/62a03773cf4b4d13db0d2149ac45142a to your computer and use it in GitHub Desktop.
Save rohanb10/62a03773cf4b4d13db0d2149ac45142a to your computer and use it in GitHub Desktop.
Dynamic keyframe animation for floating elements using vanilla CSS + JS

Dynamic keyframes for floating elements

Randomly generated floating/hovering animation in JS

All four of the circles below are using a different set of keyframes

balls

Usage

createKeyframe('levitate', generateRandomDisplacements());

Output

@keyframes levitate {0% {transform:translateX(0px) translateY(0px);}5% {transform:translateX(-4px) translateY(6px);}....

You can use a css insertion library like this one to add this output to the <head> of your html file.

CSS

.circle-1 {
	animation: levitate 45s ease-in-out infinite;
}

@keyframes levitate {
	0% {
		transform: translateX(0px)  translateY(0px);
	} 
	5% {
		transform:translateX(-4px) translateY(6px);
	}
	...
}

Change the const options for different results.

For the gif above, I used the default options specified below.

const UNIT = 'px'; // Switch to % if needed
const M_D = 10; // Maximum displacement from origin 0, 0
const STEPS = 20; // Number of intervals from 0% to 100%
function generateRandomDisplacements() {
var keys = {
0: {transform: `translateX(0${UNIT}) translateY(0${UNIT})`},
100: {transform: `translateX(0${UNIT}) translateY(0${UNIT})`}
};
var randX = 0;
var randY = 0;
for (var i = 100/STEPS; i < 100; i += 100/STEPS) {
// if random value more than max displacement, ensure movement in opposite direction
randX += (randX > M_D ? -1 : randX < -M_D ? 1 : coinFlip()) * Math.floor(Math.random() * M_D);
randY += (randY > M_D ? -1 : randY < -M_D ? 1 : coinFlip()) * Math.floor(Math.random() * M_D);
keys[i] = {
transform: `translateX(${randX}${UNIT}) translateY(${randY}${UNIT})`
}
}
return keys;
}
function createKeyframe(name, frames) {
if (typeof name !== 'string' || typeof frames !== 'object') return;
var css = '@keyframes ' + name + ' {'
Object.keys(frames).map(function (keyframeKey) {
css += keyframeKey + '% {'
Object.keys(frames[keyframeKey]).map(function (propertyKey) {
// Convert json key from camelcase to css hyphenation (eg. borderRadius -> border-radius)
css += propertyKey.replace(/([A-Z])/g, "-$1").toLowerCase() + ':' + frames[keyframeKey][propertyKey] + ';'
});
css += '}';
});
css += '}';
return {name, css}
}
// return 1 or -1
function coinFlip() {
return Math.round(Math.random()) * 2 - 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment