JSFiddle - React, Tailwind, and code Playground

by justinwinter

HTML

<!DOCTYPE html>
<html><head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>Animated Bubbles</title>
		<link rel="stylesheet" href="movingbubbles.css" type="text/css" />
		<style>
			/* Start slider CSS */
			#sliderContainer {
				position:absolute;
				top:20px;
				right:20px;
				background-color:#fff;
				background-image:linear-gradient(to bottom, #fff, #eee);
				border-radius:5px;
				padding:10px;
				box-shadow:0 5px 5px rgba(0, 0, 0, .2);
				text-shadow:0 1px #fff;
				opacity:0.2;
				transition:opacity linear 0.25s;
				font-family:Arial, sans-serif;
			}
			#sliderContainer:hover {
				opacity:1;
			}
			#sliderContainer h3 {
				margin:0;
				text-align:center;
			}
			#sliderContainer strong {
				width:115px;
				display:inline-block;
			}
			#sliderContainer input {
				width:200px;
				margin:0;
			}
			#sliderContainer span {
				padding:5px 0;
				width:5%;
			}
			#sliderContainer hr {
				background:#999;
				box-shadow:0 1px #fff;
				border:0;
				height:1px;
			}
			/* End slider CSS */
		</style>
        <script src="movingbubbles.js" type="text/javascript"></script>
        <script type="text/javascript">
        	/**
        	 * A function for the settings sliders to properly update bubbleOptions
        	 * @this {Window}
        	 * @param {[object HTMLInputElement]} slider The slider element
        	 * @param {String} bubbleSetting The variable name of bubbleOptions that the slider modifies
        	 */
        	function sliderUpdate(slider, bubbleSetting) {
        		var value = parseFloat(slider.value);
        		//Special cases
        		//The bubble-pixel ratio requires changing the number of bubbles
        		//And if the bubble cap is lower than the number of bubbles,
        		//then the bubbles also need to be changed
        		if(bubbleSetting == 'ratio' ||
        		   (bubbleSetting == 'maxBubbles' && bubbleOptions.bubbles.length > value)) {
        			var bubbleContainer =...

CSS

/*
 * CSS for the moving bubbles
 * Makes sure the bubble container appears behind the contents of the page
 * Gerard Godone-Maresca
 */
html, body {
	padding:0;
	margin:0;
	min-height:100%;
	background-color:#50afe4;
	background-image:linear-gradient(to bottom,#57B7E0,#3C799D);
	background-attachment:fixed;
}
html * { z-index: 1; position:relative; }
#bubbleContainer {
	z-index:0;
	overflow:hidden;
	position:fixed;
	height:100%;
	width:100%;
}
#bubbleContainer div {
	position:fixed;
	z-index:-1;
	border-radius:1000px;
}

JavaScript

/**
 * Creates an animated bubble background
 * @author Gerard Godone-Maresca
 */

/*
 * An object that stores different settings for the bubbles
 */
var bubbleOptions = {
	maxBubbles     : 250,   //A bubble ceiling, for high resolution monitors
	timer          : -1,    //The interval time
	tick           : 100,   //The tick speed
	bubbles        : [],    //The array of bubbles
	hue            : 188,   //The hue
	hueRand        : 20,    //The hue variance
	saturation     : 63,    //The saturation
	saturationRand : 10,    //The saturation variance
	light          : 57,    //The lightness
	lightRand      : 10,    //The lightness variance
	opacityFactor  : 3,     //What Math.random() opacity should be divided by
	minOpacity     : 0.1,   //The minimum opacity
	ratio          : 45000, //The bubble:pixel ratio
	update		   : function(tick) { //Function to change the tick timer
		//Since IE8 and below don't support HSLA colors,
		//do nothing for these browsers
		if(!document.addEventListener) return;
		window.clearInterval(this.timer);
		if(!tick) tick = this.tick;
		if(!this.bubbles.length) this.bubbles = instantiateBubbles();
		var bubbles = this.bubbles;
		this.timer = window.setInterval(
			function() {
				for(var i = 0; i < bubbles.length; i++)
					bubbles[i].move();
			},
			tick
		);
	}
};

//Instantiate the bubble on page load
if(window.onload) {
	windowOnLoad = window.onload;
	window.onload = function() {
		windowOnLoad();
		bubbleOptions.update();
	}
} else window.onload = function() { bubbleOptions.update(); };

/**
 * instantiateBubbles creates the array of bubble objects, and adds them to <body>
 * @returns {Array} An array of bubbles
 */
function instantiateBubbles() {
	//The bubbles need a container element
	var bubbleContainer = document.getElementById("bubbleContainer");
	if(!bubbleContainer) {
		bubbleContainer = document.createElement('div');
		bubbleContainer.setAttribute('id',...