<main>
<div id="hover-pop-up" popover>
<svg class="hovercraft" viewBox="0 0 100 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="hovercraft__stream" stroke="#000" stroke-width="2" stroke-linecap="round" d="M1 9h7M1 17h7M1 25h7" />
<path d="M12 8h42c18.778 0 34 15.222 34 34v14H12V8Z" fill="#D9D9D9" stroke="#000" stroke-width="2" />
<path fill="#E12727" stroke="#000" stroke-width="2" d="M12 1h21v38H12z" />
<rect x="1" y="34" width="98" height="23" rx="11.5" fill="#8F8F8F" stroke="#000" stroke-width="2" />
<rect x="7" y="37" width="22" height="7" rx="3.5" fill="#fff" />
<rect x="37" y="14" width="14" height="14" rx="1" fill="#A0D5EB" stroke="#000" stroke-width="2" />
<path d="M58.908 14.103c1.56.135 3.87.446 6.264 1.157 2.402.714 4.82 1.812 6.655 3.48 2.71 2.463 5.168 5.17 6.754 7.243.622.813 1.086 1.5 1.38 2.017H58.994A.995.995 0 0 1 58 27V15c0-.566.438-.938.908-.897Z" fill="#A0D5EB" stroke="#000" stroke-width="2" />
<rect x="15" y="4" width="10" height="4" rx="2" fill="#fff" />
</svg>
<div>Craft!</div>
</div>
<div popoverhovertarget="hover-pop-up">Hover...</h1>
</main>
@layer normalize, open-props, base, mdl, demo;
@layer demo {
[popover] {
padding: var(--size-4);
}
[popover] {
--hide: 1;
transform: translate(-50%, calc((100 + (25 * (1 - var(--hide)))) * -1%))
scale(calc(1 - var(--hide)));
position: fixed;
top: calc(50% - (var(--font-size-4) * 0.5));
left: 50%;
margin: 0;
text-align: center;
overflow: visible;
border: 0;
border-radius: var(--radius-2);
transform-origin: 50% 100%;
}
[popover]::backdrop {
background: hsl(210 80% 50% / 0.25);
opacity: calc(1 - var(--hide, 1));
}
[popover]:before {
content: "";
width: 25%;
aspect-ratio: 1;
position: absolute;
top: 100%;
left: 50%;
border-width: inherit;
border-style: inherit;
background: white;
transform: translate(-50%, -50%) rotate(45deg);
z-index: -1;
}
[popover] > * + * {
margin-top: var(--size-2);
}
[popoverhovertarget] {
pop-up-show-delay: 1s;
}
[popover] {
pop-up-hide-delay: 1s;
}
[popover]:open,
[popover]:open::backdrop {
--hide: 0;
}
@media (prefers-reduced-motion: no-preference) {
[popover]:open .hovercraft {
animation: hover 0.25s infinite linear;
}
[popover]:open .hovercraft__stream {
animation: stream 1s infinite;
}
[popover] {
transition: transform 0.2s;
}
[popover]::backdrop {
transition: opacity 0.2s;
}
}
@keyframes stream {
0% {
transform: translateX(10px);
}
100% {
transform: translateX(-10px);
}
}
@keyframes hover {
50% {
transform: translateY(-20%);
}
}
div {
font-size: var(--font-size-4);
font-weight: var(--font-weight-9);
}
}
@layer base {
:root {
--primary-color: hsl(280 100% 50% / 0.75);
--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;
}
:where([popover]) {
margin: auto;
border-width: initial;
border-style: solid;
}
}
// Polyfill
let hoverTimer;
const HOVER_TRIGGERS = document.querySelectorAll("[popoverhovertarget]");
const tearDown = () => {
if (hoverTimer) clearTimeout(hoverTimer);
};
HOVER_TRIGGERS.forEach((trigger) => {
const popup = document.querySelector(
`#${trigger.getAttribute("popoverhovertarget")}`
);
trigger.addEventListener("pointerenter", () => {
hoverTimer = setTimeout(() => {
if (!popup.matches(":open")) popup.showPopover();
}, 500);
trigger.addEventListener("pointerleave", tearDown);
});
});