Custom Code Experiment •
Webpage Background
Source Code View HTML / CSS / JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fluid Background</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #000;
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
class GlassBlob {
constructor(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.baseSize = size;
this.vx = (Math.random() - 0.5) * 0.3;
this.vy = (Math.random() - 0.5) * 0.3;
this.angle = Math.random() * Math.PI * 2;
this.rotationSpeed = (Math.random() - 0.5) * 0.01;
this.pulsePhase = Math.random() * Math.PI * 2;
this.pulseSpeed = 0.01 + Math.random() * 0.01;
this.hueOffset = Math.random() * 360;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.angle += this.rotationSpeed;
this.pulsePhase += this.pulseSpeed;
this.size = this.baseSize + Math.sin(this.pulsePhase) * 10;
if (this.x < -200) this.x = canvas.width + 200;
if (this.x > canvas.width + 200) this.x = -200;
if (this.y < -200) this.y = canvas.height + 200;
if (this.y > canvas.height + 200) this.y = -200;
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
const gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, this.size);
gradient.addColorStop(0, `hsla(${this.hueOffset}, 90%, 70%, 0.7)`);
gradient.addColorStop(0.3, `hsla(${this.hueOffset + 80}, 85%, 65%, 0.6)`);
gradient.addColorStop(0.6, `hsla(${this.hueOffset + 160}, 80%, 60%, 0.4)`);
gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
ctx.fillStyle = gradient;
ctx.filter = 'blur(30px)';
ctx.beginPath();
const points = 8;
for (let i = 0; i < points; i++) {
const a = (i / points) * Math.PI * 2;
const r = this.size * (0.8 + Math.sin(a * 3 + this.pulsePhase) * 0.2);
const x = Math.cos(a) * r;
const y = Math.sin(a) * r;
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
}
ctx.closePath();
ctx.fill();
ctx.filter = 'none';
ctx.restore();
}
}
class WaveLine {
constructor(startY) {
this.points = [];
this.startY = startY;
this.offset = 0;
this.speed = 0.02;
this.amplitude = 50 + Math.random() * 50;
this.frequency = 0.01 + Math.random() * 0.01;
this.numLines = 20;
this.spacing = 8;
}
update() {
this.offset += this.speed;
}
draw() {
for (let line = 0; line < this.numLines; line++) {
ctx.strokeStyle = `rgba(255, 255, 255, ${0.15 - line * 0.005})`;
ctx.lineWidth = 1.5;
ctx.beginPath();
for (let x = 0; x <= canvas.width; x += 5) {
const y = this.startY +
Math.sin(x * this.frequency + this.offset) * this.amplitude +
line * this.spacing;
if (x === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
}
ctx.stroke();
if (line % 3 === 0) {
for (let x = 0; x <= canvas.width; x += 80) {
const y = this.startY +
Math.sin(x * this.frequency + this.offset) * this.amplitude +
line * this.spacing;
ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2);
ctx.fill();
}
}
}
}
}
class DiagonalStreak {
constructor() {
this.reset();
}
reset() {
this.x = Math.random() * canvas.width;
this.y = -100;
this.length = 100 + Math.random() * 150;
this.speed = 2 + Math.random() * 3;
this.opacity = 0.1 + Math.random() * 0.2;
}
update() {
this.x += this.speed * 0.5;
this.y += this.speed;
if (this.y > canvas.height + 100) {
this.reset();
}
}
draw() {
const gradient = ctx.createLinearGradient(
this.x, this.y,
this.x + this.length * 0.5, this.y + this.length
);
gradient.addColorStop(0, `rgba(255, 255, 255, 0)`);
gradient.addColorStop(0.5, `rgba(255, 255, 255, ${this.opacity})`);
gradient.addColorStop(1, `rgba(255, 255, 255, 0)`);
ctx.strokeStyle = gradient;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x + this.length * 0.5, this.y + this.length);
ctx.stroke();
}
}
class Star {
constructor() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.size = 1 + Math.random() * 2;
this.opacity = Math.random();
this.twinkleSpeed = 0.02 + Math.random() * 0.02;
}
update() {
this.opacity += this.twinkleSpeed;
if (this.opacity > 1 || this.opacity < 0) {
this.twinkleSpeed *= -1;
}
}
draw() {
ctx.fillStyle = `rgba(255, 255, 255, ${this.opacity * 0.5})`;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
}
function drawCornerGrids() {
const dotSize = 4;
const spacing = 20;
const rows = 2;
const cols = 8;
ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
ctx.beginPath();
ctx.arc(
canvas.width - 50 - c * spacing,
50 + r * spacing,
dotSize,
0,
Math.PI * 2
);
ctx.fill();
}
}
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
ctx.beginPath();
ctx.arc(
50 + c * spacing,
canvas.height - 50 - r * spacing,
dotSize,
0,
Math.PI * 2
);
ctx.fill();
}
}
}
const blobs = [];
for (let i = 0; i < 8; i++) {
blobs.push(new GlassBlob(
Math.random() * canvas.width,
Math.random() * canvas.height,
60 + Math.random() * 80
));
}
const waveLines = [
new WaveLine(canvas.height * 0.5)
];
const streaks = [];
for (let i = 0; i < 8; i++) {
streaks.push(new DiagonalStreak());
}
const stars = [];
for (let i = 0; i < 80; i++) {
stars.push(new Star());
}
function animate() {
const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
gradient.addColorStop(0, '#0f0a1f');
gradient.addColorStop(0.3, '#1a0f2e');
gradient.addColorStop(0.6, '#1f0a33');
gradient.addColorStop(1, '#0a1628');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
stars.forEach(star => {
star.update();
star.draw();
});
streaks.forEach(streak => {
streak.update();
streak.draw();
});
blobs.forEach(blob => {
blob.update();
blob.draw();
});
waveLines.forEach(wave => {
wave.update();
wave.draw();
});
drawCornerGrids();
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>