[ Note: Looking for a cross-browser solution that does not flash the body's background momentarily between each wave of goo as seen in ccprog's answer; Ideally, the solution should not involve waiting until the end of the first wave to begin displaying the second wave, so that both waves can run concurrently. I am willing to forego dynamically randomized goop in order for an ideal solution. ]
Does anybody know how I can 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 show or expose the red body element (body
) or, for that matter, any other element below it in the stacking context? Is it possible?
Notably, the reason I have given the container (.goo-container
) a solid background is because I was using this to cover up the loading process of the rest of the website, whereby I was hoping the orange goo (.goo-two
) can be used to reveal the content. It gets even trickier because the orange goo starts dripping before the brown goo finishes, which would be the perfect time to change the background of the contianer (.goo-container
) from skyblue
to transparent
, although a semi-transparent gradient as the background can likely be used to still achieve this. (Either that or something altogether different like duplicating the orange layer and use one to clip the brown path and the other to clip skyblue layer.)
Any ideas?
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>
minlength
andmaxlength
forinput
elements is surprisingly just beginning to receive support) – Freestandingsvg { display: none }
. seems to work fine when you disable this – Freestandingdiv
element per pixel ofwidth
and set different heights to imitate a wave/goo and then coordinate the manipulation of theheight
of everydiv
to make the goo lively and also slide down the screen. do you think any devices, let alone mobile devices, would be able to handle this? i guess on mobile, far fewerdiv
elements would be needed because theirwidth
is typically less than desktop – Freestanding