A configurable and animated HTML background, relatively lightweight HTML, JavaScript and embedded CSS. Colors, size, speed et cetera can all be easily configured.
View in full window https://cyberdream.se/abstract/index.htm
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animated Background</title>
<style>
:root {
--bg-color: #2b2b2b; /* something very dark */
--rect-color-1: #8f8f8f; /* dark gray */
--rect-color-2: #f7f7f7; /* white ish */
--rect-color-3: #ffa600; /* orange */
--rect-shadow: 16px 16px 32px rgba(0, 0, 0, 0.9);
--min-rect-size: 32%; /* 30px */
--max-rect-size: 256%; /* 100px */
--num-rects: 32;
--animation-speed: 512s;
--speed-variation: 64s;
}
body {
margin: 0;
background-color: var(--bg-color);
overflow: hidden;
}
.rectangle {
position: absolute;
border-radius: 16%;
box-shadow: var(--rect-shadow);
opacity: 1; /* 1 */
}
</style>
</head>
<body>
<script>
const rootStyles = getComputedStyle(document.documentElement);
const config = {
bgColor: rootStyles.getPropertyValue('--bg-color'),
colors: [
rootStyles.getPropertyValue('--rect-color-1').trim(),
rootStyles.getPropertyValue('--rect-color-2').trim(),
rootStyles.getPropertyValue('--rect-color-3').trim()
],
shadow: rootStyles.getPropertyValue('--rect-shadow').trim(),
minSize: parseInt(rootStyles.getPropertyValue('--min-rect-size')),
maxSize: parseInt(rootStyles.getPropertyValue('--max-rect-size')),
numRects: parseInt(rootStyles.getPropertyValue('--num-rects')),
animationSpeed: parseFloat(rootStyles.getPropertyValue('--animation-speed')),
speedVariation: parseFloat(rootStyles.getPropertyValue('--speed-variation')),
};
const createRectangle = () => {
const rect = document.createElement('div');
const size = Math.random() * (config.maxSize - config.minSize) + config.minSize;
rect.classList.add('rectangle');
rect.style.width = `${size}px`;
rect.style.height = `${size}px`;
rect.style.backgroundColor = config.colors[Math.floor(Math.random() * config.colors.length)];
rect.style.left = `${Math.random() * window.innerWidth}px`;
rect.style.top = `${Math.random() * window.innerHeight}px`;
const animationDuration = config.animationSpeed + (Math.random() - 0.5) * config.speedVariation;
rect.style.animation = `move ${Math.abs(animationDuration)}s linear infinite alternate`;
document.body.appendChild(rect);
return rect;
};
const setKeyframes = () => {
const styleSheet = document.styleSheets[0];
for (let i = 0; i < config.numRects; i++) {
const moveKeyframes = `
@keyframes move-${i} {
0% {
transform: translate(0, 0);
}
25% {
transform: translate(${Math.random() * 200 - 100}px, ${Math.random() * 200 - 100}px);
}
50% {
transform: translate(${Math.random() * 200 - 100}px, ${Math.random() * 200 - 100}px);
}
75% {
transform: translate(${Math.random() * 200 - 100}px, ${Math.random() * 200 - 100}px);
}
100% {
transform: translate(0, 0);
}
}
`;
styleSheet.insertRule(moveKeyframes, styleSheet.cssRules.length);
}
};
const init = () => {
setKeyframes();
for (let i = 0; i < config.numRects; i++) {
const rect = createRectangle();
rect.style.animationName = `move-${i}`;
}
};
init();
window.addEventListener('resize', () => {
document.querySelectorAll('.rectangle').forEach(rect => rect.remove());
init();
});
</script>
</body>
</html>