@layer normalize, open-props, base, mdl, demo;
@layer demo {
[popover] {
padding: var(--size-4);
}
[popover] {
box-shadow: var(--shadow-5);
position: fixed;
top: 50%;
left: 50%;
margin: 0;
padding: 0;
border: 0;
}
.balloon {
cursor: pointer;
font-size: var(--font-size-fluid-1);
font-weight: var(--font-weight-9);
color: var(--gray-0);
overflow: visible;
width: 12vmin;
aspect-ratio: 0.8 / 1;
height: auto;
background: hsl(var(--hue) 50% 50% / 0.75);
border-radius: 50% 50% 50% 50% / 45% 45% 55% 55%;
filter: brightness(var(--brightness, 1));
transition: filter 0.2s, transform 0.2s;
transform: translate(-50%, -50%) translateX(calc(var(--index, 0) * 110%))
translateY(0) scale(var(--scale, 1));
/*animation: float calc(var(--d, 1) * 1s) calc(var(--delay, 0) * -1s) infinite linear both;*/
}
[popover]:hover {
--scale: 1.2;
--brightness: 1.2;
}
[popover]:open {
animation: float calc(var(--float-speed) * 10s) forwards,
bob calc(var(--bob-speed) * 10s) infinite ease-in-out;
}
@keyframes float {
0% {
transform: translate(-50%, -50%) translateX(calc(var(--index, 0) * 110%))
translateY(100vh) translateY(0vh);
}
}
@keyframes bob {
50% {
transform: translate(-50%, -50%) translateX(calc(var(--index, 0) * 110%))
translateY(0) translateY(-25%);
}
}
.balloon:before {
content: "";
position: absolute;
width: 20%;
height: 30%;
background: blue;
top: 8%;
left: 16%;
border-radius: 50%;
transform: rotate(40deg);
background: var(--shine);
}
.balloon__content {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
flex-direction: column;
gap: var(--size-4);
font-weight: var(--font-weight-6);
}
.balloon__handle {
--chord: hsl(45, 100%, 40%);
width: 2%;
height: 60%;
background: var(--chord);
top: 100%;
left: 50%;
transform: translate(-50%, 0);
position: absolute;
}
.balloon__handle:before,
.balloon__handle:after {
content: "";
position: absolute;
height: 5%;
transform: translate(-50%, 0);
border-radius: 25% / 50%;
left: 50%;
}
.balloon__handle:before {
top: 0;
background: var(--chord);
width: 500%;
}
.balloon__handle:after {
top: 5%;
background: var(--primary-color);
width: 700%;
}
@keyframes float-up {
from {
transform: translate(-50%, -50%) translateX(calc(var(--index) * 125%))
scale(calc(1 + var(--scale, 0))) translateY(100vh);
}
}
}
@layer base {
:root {
--shine: hsl(0 0% 100% / 0.75);
--speed: 1s;
}
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
min-height: 100vh;
font-family: "Google Sans", sans-serif, system-ui;
align-content: center;
overflow: hidden;
}
:where([popup]) {
margin: auto;
border-width: initial;
border-style: solid;
}
}
const AUDIO_POP = new Audio("https://assets.codepen.io/5928893/pop.mp3");
const WORD = "Pop-up";
const START_INDEX = WORD.length / -2 + 0.5;
for (let p = 0; p < WORD.length; p++) {
const POPUP = Object.assign(document.createElement("button"), {
popover: "manual",
className: "balloon",
id: WORD.charAt(p),
defaultOpen: true,
title: `Pop "${WORD.charAt(p)}"`,
innerHTML: `
<span class="balloon__content">
<span class="balloon__letter">${WORD.charAt(p)}</span>
<span class="balloon__handle"></div>
</span>
`,
style: `
--index: ${START_INDEX + p};
--hue: ${Math.random() * 359};
--bob-speed: ${Math.random() + 0.5};
--float-speed: ${Math.random() + 0.5};
`
});
document.body.appendChild(POPUP);
POPUP.addEventListener("click", () => {
AUDIO_POP.currentTime = 0;
AUDIO_POP.play();
POPUP.hidePopover();
Object.assign(POPUP, {
style: `
--index: ${START_INDEX + p};
--hue: ${Math.random() * 359};
--bob-speed: ${Math.random() + 0.5};
--float-speed: ${Math.random() + 0.5};
`
});
requestAnimationFrame(() => POPUP.showPopover());
});
// Because defaultopen does not work for some reason?
POPUP.showPopover();
}