This lightweight water/liquid effect was made using SVG filters and pure JavaScript.
The technology is very new, and not all browsers support it.
In HTML we have to create an SVG filter.
<!DOCTYPE html>
<html lang="en">
<head>
<title>SVG Filter Water Effect</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="block water-1">
<div class="title">
<h1>Cool effect, huh?</h1>
<div class="options">
<div class="option is-active" data-value="water-1">Image Water</div>
<div class="option" data-value="water-2">Gradient Water</div>
<div class="option" data-value="clouds">Clouds</div>
<div class="option" data-value="gradient">Gradient</div>
</div>
</div>
</div>
<!-- This is the filter that is defined inside the SVG element. -->
<svg version='1.1' xmlns='http://www.w3.org/2000/svg' style="display: none;">
<defs>
<filter id='wave'>
<feturbulence basefrequency='0 0' id='turbulence' numoctaves='1' result='noise' seed='13'></feturbulence>
<fedisplacementmap id='displacement' in2='noise' in='SourceGraphic' scale='126'></fedisplacementmap>
</filter>
</defs>
</svg>
<script src="js/script.js"></script>
</body>
</html>
In CSS we must set the SVG filter id to the filter property.
* {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
.block {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
.block:before {
content: '';
position: absolute;
top: -100px;
bottom: -100px;
left: -100px;
right: -100px;
background: -o-repeating-linear-gradient(102deg, #c0cdd7 0px, #c0cdd7 150px, #c7bea5 200px);
background: repeating-linear-gradient(-12deg, #c0cdd7 0px, #c0cdd7 150px, #c7bea5 200px);
-webkit-filter: url(#wave); /* Here we set filter property to the element */
filter: url(#wave);
z-index: 1;
}
.block.water-1:before {
background: transparent;
background-image: url(https://cdn.pixabay.com/photo/2015/07/02/10/23/water-828746_960_720.jpg);
background-size: cover;
background-position: center center;
}
.block.water-2:before {
background: -o-repeating-linear-gradient(102deg, #008ec9 10%, #05419f 20%, #008ec9 30%);
background: repeating-linear-gradient(-12deg, #008ec9 10%, #05419f 20%, #008ec9 30%);
}
.block.clouds:before {
background: -o-repeating-linear-gradient(102deg, #E6E6E1 0%, #657C90 10%, #3778A2 30%, #E6E6E1 40%, #657C90 50%, #E6E6E1 70%);
background: repeating-linear-gradient(-12deg, #E6E6E1 0%, #657C90 10%, #3778A2 30%, #E6E6E1 40%, #657C90 50%, #E6E6E1 70%);
}
.block.gradient:before {
background: -o-repeating-linear-gradient(102deg, #c0cdd7 0px, #d773a0 150px, #c7bea5 200px, #008ec9 400px, #05419f 500px, #008ec9 700px, #c7bea5 750px, #d773a0 800px, #008ec9 850px, #c0cdd7 1100px);
background: repeating-linear-gradient(-12deg, #c0cdd7 0px, #d773a0 150px, #c7bea5 200px, #008ec9 400px, #05419f 500px, #008ec9 700px, #c7bea5 750px, #d773a0 800px, #008ec9 850px, #c0cdd7 1100px);
}
.title {
position: relative;
z-index: 3;
text-align: center;
padding: 0 30px;
font-family: Arial, sans-serif;
color: #FFFFFF;
}
h1 {
font-size: 3rem;
}
/* You don't need the code below, it's for options (Water Image, Water Gradient, Clouds Gradient, Gradient) */
.options {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
margin-top: 20px;
}
.options .option {
padding: 10px 20px;
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
text-align: center;
cursor: pointer;
border: 2px solid transparent;
-webkit-transition: border-color .5s;
-o-transition: border-color .5s;
transition: border-color .5s;
}
.options .option.is-active {
border-color: #FFFFFF;
}
@media (max-width: 768px) {
.options {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
}
To animate the SVG filter we have to change the value of the baseFrequency attribute of this filter.
The animation will be rendered recursively using requestAnimationFrame method.
(function () {
let step = 0.0001,
filter = document.querySelector("#turbulence"),
rad = Math.PI / 180;
function filterAnimation() {
step += 0.25;
x = 0.005 + 0.001 * Math.cos(step * rad);
y = 0.01 + 0.005 * Math.sin(step * rad);
xy = x.toString() + ' ' + y.toString();
filter.setAttributeNS(null, 'baseFrequency', xy);
window.requestAnimationFrame(filterAnimation);
}
window.requestAnimationFrame(filterAnimation);
})();
// You don't need the code below, it's to switch between options (Water Image, Water Gradient, Clouds Gradient, Gradient)
(function () {
let block = document.querySelector('.block');
let options = document.querySelectorAll('.option');
options.forEach((option) => {
option.addEventListener('click', (e) => {
block.className = 'block ' + e.target.dataset.value;
options.forEach((option) => { option.classList.remove('is-active'); });
e.target.classList.add('is-active');
});
});
})();