<div id="bubble-container" class="animakuz-container gradient-bg-blue">
  <!--   bubble prototype -->
<!--   <div class="bubble bubble-part bubble-1">
    <div class="soft-light base-light bubble-part">
    </div>
    <div class="mid-light top-light bubble-part">
    </div>    
    <div class="mid-light bottom-light bubble-part">
    </div>
    <div class="hard-light off-light-1 bubble-part">
    </div>
    <div class="hard-light off-light-2 bubble-part">
    </div>
  </div> -->
  
  <!--   options -->
  <button id="btn-show-options">^</button>
  
  <div id="options" class="box">
    <p class="options-title">
      <span class="title-text">Bubble Options</span>
      <button id="btn-hide-options">X</button>
    </p>
    <p class="options-body">
      <label>Bubble Density</label>
      <input id="txt-bubble-density" type="text" value="10">
      <button id="btn-generate">Generate</button>
    </p>
  </div>
  
<!--   show error message on input to bubble density -->
  <div id="message-box" class="box message-box error-message">    
    <p id="message-line" class="message">
      <span id="message-icon" class="error-icon">!</span>
      <span id="message-text">Error</span>
    </p>
    <button id="message-button">OK</button>
  </div>
</div>
/* interface */
body, html {
  overflow: hidden;
}

/* boxes */
.box {
  border-radius: 5px;
  border: 1px solid rgba(200,200,250,0.4);
  background-color: rgba(150,150,200,0.4);
  box-shadow: 0 2px 4px rgba(50,50,100,0.4);  
}

.active-box {
  display: block !important;
}

#btn-show-options, #options {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
}

#btn-show-options {
  display: block;
  bottom: 10px;
  height: 32px;
  padding: 4px 14px 0;
  font-size: 32px;
  border-radius: 4px;
  cursor: pointer;
  border: 1px solid rgba(200,200,250,0.2);
  box-shadow: 0 2px 4px rgba(50,50,100,0.2);
  background-color: rgba(60,60,200,0.2);
  color: rgba(220,220,240,0.8);
}

#btn-show-options:hover {
  background-color: rgba(60,60,200,0.8);
  color: rgba(220,220,240,1);
}

#options {
  display: none;
  bottom: 10%;
}

  .options-title {
    margin: 0;
    height: 24px;
    line-height: 24px;
    background-color: rgba(50,50,150,0.2);
    border-radius: 5px 5px 0 0;
  }

    .options-title .title-text {
      margin-left: 10px;
      color: #dedede;
    }
    
    #btn-hide-options {
      cursor: pointer;
      position: absolute;
      right: 0;
      top: 0;
      border-radius: 5px;
      border: 0;
      height: 24px;
      width: 24px;
      font-size: 12px;
      font-weight: bold;
      background-color: rgba(200,60,60,0.8);
      color: rgb(240,220,220);
    }
    
    #btn-hide-options:hover {
      color: rgba(200,60,60,0.8);
      background-color: rgb(240,220,220);
    }
    
  .options-body {
    margin: 20px 20px 10px;
  }
  
    .options-body label {
      color: #dedede;
      margin-right: 10px;
    }
    
    #txt-bubble-density {
      width: 40px;
      text-align: center;
      border: 1px solid rgba(0,0,0,0.14);
      border-radius: 4px;
      padding: 2px 5px;
    }
    
    #btn-generate {
      border: 0;
      cursor: pointer;
      border-radius: 5px;
      padding: 8px 10px;
      margin-left: 4px;
      background-color: rgba(20,150,20, 0.8);
      color: rgb(220,240,220);
    }
    
    #btn-generate:hover {
      background-color: rgb(220,240,220);
      color: rgba(10,100,10, 0.8);   
    }

@media (max-width: 767px) {
  #options {
    
  }
  
  .options-body label {
    display: block;
    margin: 5px auto 10px;
    text-align: center;
  } 
}

#txt-bubble-density {
  
}

#btn-generate {
  
}

.message-box {
  display: none;
  padding: 14px 20px 10px;
  position: absolute;
  top: 30%; 
  left: 50%;
  transform: translateX(-50%);  
  text-align: center;
}

.message-box .message {
  margin: 0 auto 15px;
  /* font-weight: bold;*/
  text-align: center;
}

.message-box #message-icon {
  display: inline-block;
  margin-right: 5px;
  width: 20px;
  height: 20px;
  line-height: 22px;
  text-align: center;
  border-radius: 50%;
  color: #fff;
  
}

.message-box #message-button {
  border: 0;
  border-radius: 5px;
  padding: 4px 16px;
  cursor: pointer;
  color: #fff;
  background-color: rgba(50,100,150, 0.8);
}

.message-box #message-button:hover {
  color: rgba(50,100,150, 0.8);
  background-color: rgba(250,250,250,0.8);
}

.error-message {
  color: rgb(200,20,20);
}

.error-icon {
  background-color: rgba(255,50,50,1);
}

.confirm-message {
  color: rgb(200,250,200);
}

.confirm-icon {
  background-color: rgba(0,150,0,1);
}

/*-- bubble construction */
.bubble-part {
  border-radius: 50%;
  position: absolute;
}

.bubble {
  background-color: rgba(50,50,100,0.1);
}

.soft-light {
  background: radial-gradient(rgba(255,255,255,0.3),
              rgba(255,255,255,0.1), rgba(255,255,255,0));
}

.mid-light {  
  background: radial-gradient(rgba(255,255,255,0.4),
              rgba(255,255,255,0.1), rgba(255,255,255,0));
  transform: rotateZ(-30deg);
}

.hard-light {  
  background: radial-gradient(rgba(255,255,255,0.4), 
              rgba(255,255,255,0.4));
  transform: rotateZ(-30deg);
}

.base-light {
  top: 3%;  
  left: 3%;  
  width: 94%;
  height: 94%;
}

.top-light {
  top: 10%;
  left: 15%;  
  width: 40%;
  height: 30%;
}

.bottom-light {
  width: 60%;
  height: 50%;
  top: 40%;
  left: 35%;
  transform: rotateZ(-40deg);
}

.off-light-1 {
  width: 6%;
  height: 6%;
  top: 35%;
  left: 30%;
}

.off-light-2 {
  width: 10%;
  height: 10%;
  top: 50%;
  left: 25%;
  opacity: 0.8;
}

/*--bubble animation*/
@keyframes bubbleRise {
  from {
    top: 100%;
  }
  
  to {
    top: -20%;
  }
}
var baseFunc = {
  getRandomInt: function(min, max) {
    //get random integer between a specific range
    //Source - Ionuț G. Stan - StackOverflow - Answer 06/10/09
    return Math.floor(Math.random() * (max - min + 1)) + min;
  },
  
  addClass: function(element, classesToAdd) {
    //add a class or multiple classes to an element
    var newClassName = element.className.trim().replace(/\s+/g,' ') + ' ';
    var newClasses   = classesToAdd.split(/\s+/);		
    var len          = newClasses.length;
    var ind          = 0;

    while(ind < len) { 
      var testTerm = new RegExp(newClasses[ind] + ' ');

      if (!testTerm.test(newClassName)) {
        //current className doesn't contain class - add it
        newClassName += newClasses[ind] + ' ';			
      }  

      ind++;
    }  

    element.className = newClassName.trim();
  },

  removeClass: function(element, classesToRemove) { 
    //remove a class or multiple classes from an element
    var newClass = element.className.trim().replace(/\s+/g,' ') + ' ';
    var classes  = classesToRemove.split(/\s+/);
    var ind      = classes.length;

    while(ind--) { 
      //remove class
      newClass = newClass.replace(classes[ind] + ' ','');
    }  

    element.className = newClass.trim();
  }
};

var showBox = function(box) {
  baseFunc.addClass(box, "active-box");
};

var hideBox = function(box) {
  baseFunc.removeClass(box, "active-box");
};

var showMessage = function(message, messageType) {
  var messageBox = document.getElementById("message-box");
  var messageLine = document.getElementById("message-line");
  var messageIcon = document.getElementById("message-icon");
  var messageText = document.getElementById("message-text");
  var messageButton = document.getElementById("message-button");

  messageText.innerHTML = message;

  if (messageType === "error") {
    messageBox.className = "box message-box error-message";
    messageIcon.className = "error-icon";
    messageIcon.innerHTML = "!";

  } else if (messageType === "confirm" ) {
    messageBox.className = "box message-box confirm-message";
    messageIcon.className = "confirm-icon";
    messageIcon.innerHTML = "i";    
  }

  messageButton.onclick = function() {
    hideBox(messageBox);
  };

  showBox(messageBox);
};

var animakuzBubbles = function() { 
  var btnGenerate = document.getElementById("btn-generate");
  var btnShowOptions = document.getElementById("btn-show-options");
  var btnHideOptions = document.getElementById("btn-hide-options");
  var bubbles = [];
    
  var createBubble = function(duration, delay, depth, size, pos) {
    var bubble = document.createElement("div");
    var baseLight = '<div class="soft-light base-light bubble-part"></div>';
    var topLight = '<div class="mid-light top-light bubble-part"></div>';
    var bottomLight = '<div class="mid-light bottom-light bubble-part"></div>';
    var offLight1 = '<div class="hard-light off-light-1 bubble-part"></div>';
    var offLight2 = '<div class="hard-light off-light-2 bubble-part"></div>';
    
    //bubble properties
    baseFunc.addClass(bubble, "bubble bubble-part");
    bubble.style.width = size + "px";
    bubble.style.height = size + "px";
    bubble.style.top = "100%";
    bubble.style.left = pos + "%";
    bubble.style.opacity = depth / 100;
    
    //inner parts
    bubble.innerHTML =  baseLight + topLight + bottomLight + 
                        offLight1 + offLight2;
    
    //animation
    bubble.style.animationName = "bubbleRise";
    bubble.style.animationDuration = duration + "s";
    bubble.style.animationDelay = delay + "s";
    bubble.style.animationIterationCount = "infinite";
    
    return bubble;
  };
  
  var clearBubbles = function() {
    //clear bubbles alredy present
    var container = document.getElementById("bubble-container");
    var len = bubbles.length;
    
    while(len--) {
      container.removeChild(bubbles[len]);
    }
    
    bubbles = [];
  };
  
  var generateBubbles = function(density) {    
    var container = document.getElementById("bubble-container");
    var i;
    
    //limits
    var maxDuration = 10;
    var minDuration = 5;
    var maxDelay = 10;
    var minDelay = 1;
    var maxDepth = 10;
    var minDepth = 100;
    var maxSize = 100;
    var minSize = 20;
    var maxPos = 100;
    var minPos = 1;
    
    //bubble properties
    var bubbleDuration;
    var bubbleDelay;
    var bubbleDepth;
    var bubbleSize;
    var bubblePos;
    
    clearBubbles();
  
    for (i=0; i<density; i++) {
      bubbleDuration = baseFunc.getRandomInt(minDuration, maxDuration);
      bubbleDelay = baseFunc.getRandomInt(minDelay, maxDelay);
      bubbleDepth = baseFunc.getRandomInt(minDepth, maxDepth);
      bubbleSize = baseFunc.getRandomInt(minSize, maxSize);
      bubblePos =  baseFunc.getRandomInt(minPos, maxPos);
      
      bubbles.push(createBubble(bubbleDuration, bubbleDelay, bubbleDepth, bubbleSize, bubblePos));
      container.appendChild(bubbles[i]);      
    }
  };  
  
  btnGenerate.onclick = function() {
    //generate button click
    var txtBubbleDensity = document.getElementById("txt-bubble-density");
    var density = txtBubbleDensity.value;
    if (isNaN(density) || Number(density) <= 0) {
      //show error
      showMessage("Please enter a valid number!", "error");
    } else {  
      //generate bubbles      
      generateBubbles(density);      
    }    
  };
  
  btnShowOptions.onclick = function() {
    //show options button click
    var optionsBox = document.getElementById("options");
    showBox(optionsBox);
    btnShowOptions.style.display = "none";
  };
  
  btnHideOptions.onclick = function() {
    //close button on options box
    var optionsBox = document.getElementById("options");
    hideBox(optionsBox);
    btnShowOptions.style.display = "block";
  };
  
  generateBubbles(20);
  
};

animakuzBubbles();



External CSS

  1. https://codepen.io/animakuz/pen/YZmRxQ.css

External JavaScript

This Pen doesn't use any external JavaScript resources.