<svg class="mainSVG" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">
<defs>
	<polygon id="liquid"></polygon>
	<clipPath id="mainMask">
		<polygon points="402.1 325.43 367.12 334.05 340.15 357.94 327.38 391.63 331.72 427.4 352.19 457.05 384.09 473.79 420.12 473.79 452.02 457.05 472.49 427.4 476.83 391.63 464.05 357.94 437.08 334.05 402.1 325.43" fill="#fff" stroke="#000" stroke-miterlimit="10"/>
		</clipPath>
		<clipPath id="liquidMask">
			<use xlink:href="#liquid" />
			</clipPath>
	</defs>
      <g id="pipette1" class="glass" fill="none" stroke="#aaccfb" stroke-miterlimit="10" stroke-width="4" transform="translate(0, 38)">
<polygon class="liquid" stroke="none" points="34.28 79.01 34.28 94.68 27.91 104.62 27.91 111.41 23.32 114 18.73 111.41 18.73 104.62 12.36 94.68 12.36 79.01 34.28 79.01" fill="#5299f9"/>
<rect id="level" class="liquid" stroke="none" x="12.36" y="48.05" width="22" height="32" fill="#5299f9"/>	
				<g opacity="0.5">
          <polyline points="12.07 28.65 12.07 11.51 12.07 6.83 14.07 4 15.84 2 19.94 2 27.21 2 31.06 2 32.57 4 34.57 7.16 34.57 12.01 34.57 28.65" fill="none" stroke="#003459" stroke-miterlimit="10" stroke-width="4"/>
        <polygon points="42.05 39.01 4.59 39.01 2 36.43 2 32.19 2 31.53 4.59 28.95 4.59 28.95 42.05 28.95 44.64 31.53 44.64 36.43 42.05 39.01" fill="none" stroke="#003459" stroke-miterlimit="10" stroke-width="4"/>
        <polyline points="34.28 39.01 34.28 94.68 27.91 104.62 27.91 111.41 23.32 114.41 18.73 111.41 18.73 104.62 12.36 94.68 12.36 39.01" fill="none" stroke="#003459" stroke-miterlimit="10" stroke-width="4"/>

					</g>

				<g id="pipetteShine" opacity="0.25" stroke="none">
        <polygon points="21.63 11.58 18.15 13.1 18.25 9.3 21.73 7.79 21.63 11.58" fill="#fff"/>
        <polygon points="17.88 90.03 17.86 90.03 16.87 89.04 16.87 47.02 18.87 47.02 18.87 89.04 17.88 90.03" fill="#fff"/>
      </g>
    </g>	
 
	<g id="flask" class="glass" fill="#AACCFB" stroke="#AACCFB" stroke-miterlimit="10" stroke-width="6" >
<!--         <path d="M438.68,219.23v99.08a90,90,0,1,1-77.36,0V219.23" />
        <line x1="341.31" y1="219.23" x2="458.69" y2="219.23" /> -->
        <polyline points="444.09 221.01 444.09 320.09 476.46 348.76 491.79 389.2 486.58 432.13 462.02 467.72 423.73 487.81 380.48 487.81 342.19 467.72 317.62 432.13 312.41 389.2 327.75 348.76 360.12 320.09 360.12 221.01"  stroke-linecap="round" stroke-width="8"/>
        <line x1="343.42" y1="221.01" x2="460.79" y2="221.01"  stroke-width="8"/>		
	
      </g>	
	<g id="drip">
      <polygon class="liquid" points="3.3 4.06 0 13.72 1.86 18.5 7.93 21.59 14.11 18.92 15.79 13.72 12.33 3.7 7.89 0 3.3 4.06"/>
      <polygon points="6.71 6.76 5.22 7.96 4.88 6.08 6.37 4.88 6.71 6.76" fill="#fff" opacity="0.5"/>

		</g>
	<!-- <circle class="liquid" cx="399" cy="420" r="4" /> -->
	<rect  id="droplet" class="liquid" x="399" y="420" width="6" height="6" />
	<g clip-path="url(#mainMask)">
	<use xlink:href="#liquid" x="770" y="0" class="poly darkLiquid" opacity="0.3"/>
<use xlink:href="#liquid" class="poly" y="0"/>	
		
	<g id="bubbleGroup" stroke-width="0" fill="#FFF" opacity="1"  clip-path="url(#liquidMask)">
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
	<rect x="300" y="380" width="3" height="3" />
</g>
</g>      

      <g id="flaskShine" opacity="0.25" stroke="none">
        <polygon points="375.69 300 372.19 296.51 372.19 238.68 375.69 235.18 379.18 238.68 379.18 296.51 375.69 300" fill="#fff"/>
        <rect x="414" y="233" width="16" height="80" rx="0" ry="6" fill="#fff" opacity="0.1"/>		
        <polygon points="368.47 362.44 351.13 369.58 354.5 351.13 371.84 344 368.47 362.44" fill="#fff"/>
        <polygon points="453 407.77 464.55 422.2 443.58 452.6 421.36 464.21 417.62 459.38 434.66 444.52 453 407.77" fill="#fff"/>
      </g>	
</svg>

<!-- <a href="https://greensock.com"><img class="gsap-3-logo" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-3-logo.svg" width="150" /></a> -->
:root {
  --main-color: #E6098B;
	--bg-color: #030912;
}
body {
 background-color: var(--bg-color);
 overflow: hidden;
 text-align:center;
  display: flex;
  align-items: center;
  justify-content: center; 
}

body,
html {
 height: 100%;
 width: 100%;
 margin: 0;
 padding: 0;
}

svg {
 width: 100%;
 height: 100%;
 visibility: hidden;
 
}

.liquid {
	fill:var(--main-color);
}
#bubbleGroup {
	stroke: var(--main-color);
	fill: #222932
}
.poly {
	fill: #3A86FF;
}

.glass {
	opacity: 0.2
}

#flask {
	opacity: 0.5;
	fill:#003459;
	stroke: #003459;
}

.gsap-3-logo {
width: 20vw;
max-width: 150px;
position: fixed;
bottom: 15px;
right: 15px;
}
let select = s => document.querySelector(s),
  	selectAll = s => document.querySelectorAll(s),
		mainSVG = select('.mainSVG'),
		liquid = select("#liquid"),
		pointArray = [],
		pointValueXArray = [],
		pointValueYArray = [],
		liquidWidth = 300,
		numPoints = 30,
		dripOffset = 0.0258,
		rippleDuration = 4.6,
		rippleAmount = '+=8',
		startValX = 250,
		startValY = 400,
		colorArray = ['#E6098B', '#FFBE0B', '#FB5607', '#8338EC', '#3A86FF', '#51E5FF', '#04A777', '#F75C03', '#F71735'],
		allBubbles = gsap.utils.toArray('#bubbleGroup rect')

gsap.set(mainSVG, {
	visibility: 'visible'
})
gsap.set('.darkLiquid', {
	scaleX: -1,
	transformOrigin: '50% 50%'
})
for(let i = 0; i < numPoints; i++) {
	let p =	liquid.points.appendItem(mainSVG.createSVGPoint());
	pointArray.push(p);
	pointValueXArray.push( (i < numPoints - 2) ? startValX : ( i == numPoints - 2 ) ? 600 : 200 );
	startValX += ( liquidWidth / (numPoints-2) );	
	pointValueYArray.push( (i < numPoints - 2) ? startValY : 800 )
}

gsap.set(pointArray, {
	x: gsap.utils.wrap(pointValueXArray),
	y: gsap.utils.wrap(pointValueYArray)
})

gsap.set('#level', {
	transformOrigin: '50% 100%'
})
gsap.set('#bubbleGroup rect, #droplet', {
	transformOrigin: '50% 50%'
})
gsap.fromTo(allBubbles, {
	x: 'random(0, 200)',
	y: 'random(0, 120)',
	scale:'random(0.5, 3)',
	rotation: 'random(20, 180)',
	opacity: 1
}, {
	duration: 1,
	rotation: 'random(180, 360)',
	repeatRefresh: true,
	stagger: {
		each: 0.52,
		repeat: -1
	},
	scale: 0.1,
	y: '-=30',
	opacity: 0.1,
}).seek(100)

const makeDrip = () => {

	let currentColor = gsap.utils.random(colorArray);
	gsap.to(':root', {'--main-color': currentColor});
	
	let tl = gsap.timeline({
		defaults: {
			ease: CustomWiggle.create('', {type: 'easeOut', wiggles: gsap.utils.random(9, 12)})
		}
	});

	tl.fromTo('#pipette1', {
		x: 600,
		opacity: 0
	}, {
		duration: 1,
		x: 376,
		opacity: 1,
		ease: 'expo.inOut'
	})
.fromTo('#pipette1', {
		rotation: -95,
		transformOrigin: '50% 100%'
	}, {
		rotation: 0,
		transformOrigin: '50% 100%',
		duration: 1.5,
		ease: 'elastic(1.5, 0.83)'
	}, 0)
		.addLabel('pipetteReady')
		.fromTo('#drip', {
		scale: 0
	}, {
		duration: 1,
		scale: 1,
		transformOrigin: '50% 0%',
		ease: 'elastic(1, 0.8)'
	})
	.to('#level', {
		duration: 1,
		scaleY: 0.5,
		ease: 'elastic(1, 0.8)'
	},'pipetteReady')
		.fromTo('#drip', {
			x: 399,
			y: 155
		}, {
			x: 399,
			y: 430,
			duration: 0.38,
			ease: 'power1.in'
	})
		.addLabel('splash')
		.to('.poly', {
			fill:currentColor,
		ease: 'sine'
	}, 'splash')
		.to('#bubbleGroup', {
			stroke:currentColor,
			ease: 'sine'
	}, 'splash')
	.to(pointArray, {
		duration: gsap.utils.random(3, 5),
		y: (i) => {
			return rippleAmount
		},
		stagger: {
			each: dripOffset,
			from: 'center'
		},
	}, 'splash')	
	.to('#bubbleGroup', {
		duration: 4,
		y: '+=random(5, 10)',
		ease: 'wiggle({type:easeOut, wiggles:10})'
	}, 'splash')
	.to('#droplet', {
		duration: 0.23,
		y: 'random(-30, -60, 1)',
		rotation: 'random(20, 290)',
		ease: 'power1',
	}, 'splash')	
.to('#droplet', {
		duration: 0.23,
		y:0,
		rotation: '+=30',
		ease: 'power1.in',
	}, 'splash+=0.23')	
	.fromTo('#droplet', {
		scale: 1
	}, {
		duration: 0.23,
		scale: 0,
		transformOrigin: '50% 100%',
		ease: 'expo.in'	
	}, 'splash+=0.23')	
	.to('#level', {
		duration: 1,
		scaleY: 1,
		ease: 'expo.in'
	}, 'splash')	
	.to('#pipette1', {
		duration: 1,
		rotation: 23,
		x: 100,
		opacity: 0,
		ease: 'expo.in'
	}, 'splash')	
	
	gsap.delayedCall(4, makeDrip);
}

makeDrip()

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.jsdelivr.net/npm/gsap@3.0.1/dist/gsap.min.js
  2. https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/CustomEase3.min.js
  3. https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/CustomWiggle3.min.js