[ Note: Seeking a solution that works across all browsers without causing the body's background to flash between each wave of goo; Ideally, the solution should allow both waves to run concurrently without delay. I am willing to sacrifice dynamic randomness in the goop for an optimal solution. ]
Is there a way to make the second wave of orange goo (.goo-two
) "cut through" the first wave of brown goo (.goo-one
) and the skyblue container (.goo-container
) to reveal the red body element (body
) or any other element beneath it in the stacking context? Is this even possible?
I have given the container (.goo-container
) a solid background to hide the loading process of the website content, with the intention of using the orange goo (.goo-two
) to show the content. However, a challenge arises as the orange goo begins dripping before the brown goo finishes, creating an opportunity to change the background of the container from skyblue
to transparent
, possibly using a semi-transparent gradient. Alternatively, a different approach like duplicating the orange layer could be considered - using one to cut through the brown path and the other to cut through the skyblue layer.
Any suggestions or thoughts on how to achieve this effect?
const
gooCont = document.querySelector('div.goo-container'),
gooOne = gooCont.querySelector('div.goo-one'),
gooTwo = gooCont.querySelector('div.goo-two'),
rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min
gooCont.style.setProperty('--translateY', `translateY(-${innerWidth * 0.21 / innerHeight * 100 + 100}%)`)
generateGoo(gooOne)
function generateGoo(goo) {
const
randQty = rand(20,30),
unit = innerWidth / (randQty - 1) / innerWidth * 100
if (getComputedStyle(goo).display === 'none') goo.style.display = 'block'
for (let i = 0; i < randQty; i++) {
const
div = document.createElement('div'),
minWidthPx = innerWidth < 500 ? innerWidth * 0.1 : innerWidth * 0.05,
minMaxWidthPx = innerWidth < 500 ? innerWidth * 0.2 : innerWidth * 0.1,
widthPx = rand(minWidthPx, minMaxWidthPx),
widthPerc = widthPx / innerWidth * 100,
heightPx = rand(widthPx / 2, widthPx * 3),
heightPerc = heightPx / gooCont.getBoundingClientRect().height * 100,
translateY = rand(45, 70),
targetTranslateY = rand(15, 100),
borderRadiusPerc = rand(40, 50)
div.style.width = widthPerc + '%'
div.style.height = heightPerc + '%'
div.style.left = i * unit + '%'
div.style.transform = `translate(-50%, ${translateY}%)`
div.style.borderRadius = borderRadiusPerc + '%'
div.setAttribute('data-translate', targetTranslateY)
goo.appendChild(div)
}
goo.style.transform = `translateY(0)`
goo.childNodes.forEach(
v => v.style.transform = `translateY(${v.getAttribute('data-translate')}%)`
)
}
setTimeout(() => {
gooTwo.innerHTML = ''
generateGoo(gooTwo)
}, 2300)
html,
body {
width: 100%;
height: 100%;
margin: 0;
background: red;
}
div.goo-container {
--translateY: translateY(-165%);
z-index: 1;
width: 100%;
height: 100%;
position: fixed;
overflow: hidden;
background: skyblue;
}
div.goo-container > div.goo-one,
div.goo-container > div.goo-two {
width: 100%;
height: 100%;
position: absolute;
transform: var(--translateY);
filter: url('#goo-filter');
background: #5b534a;
transition: transform 2.8s linear;
}
div.goo-container > div.goo-one > div,
div.goo-container > div.goo-two > div {
position: absolute;
bottom: 0;
background: #5b534a;
transition: transform 2.8s linear;
}
div.goo-container > div.goo-two {
display: none;
transition: transform 2.8s linear;
}
div.goo-container > div.goo-two,
div.goo-container > div.goo-two > div {
background: orange;
}
svg {
/* Prevents effect on Firefox */
/* display: none; */
}
<div class='goo-container'>
<div class='goo-one'></div>
<div class='goo-two'></div>
</div>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1'>
<defs>
<filter id='goo-filter'>
<feGaussianBlur in='SourceGraphic' stdDeviation='10' result='blur' />
<feColorMatrix in='blur' mode='matrix' values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7' result='goo' />
<feBlend in='SourceGraphic' in2='goo' />
</filter>
</defs>
</svg>