Popup generator · single file HTML
Popups that ship themselves.
Shape a popup on the canvas, watch it behave, then copy one self-contained HTML block. No libraries, no accounts, no tracking baked in.
What you export
<div class="pf-overlay">
<style> … </style>
<script> … </script>
6.5 kB output0 deps4 triggers
01
Start from
02
Content
03
Look
Palette
Position
Animation
04
Behavior
Trigger
Show again
Keeps storage keys unique per popup.
Esc closes · focus returns
your-site.com
liveNorthwind
ShopStoryJournal
Get the good stuff first
Join 4,200 readers who get one short email each Friday with the best finds, tools and ideas.
opens after 4s · once per session
Built into the snippet
- Esc key and overlay dismissal
- Focus moved into the dialog
- Scroll lock while open
- Reduced-motion respect
- Session or permanent memory
- Mobile breakpoint included
05 Embed
Copy once, paste before </body>.
The block carries its own styles and script. It inherits your page font and stays out of the way of everything else.
html · css · js6.5 kB
<!-- Popup embed generated with Popforge. Paste this before </body>. -->
<div class="pf-overlay" id="pf-popforge" data-position="center" data-animation="scale" aria-hidden="true">
<div class="pf-card" role="dialog" aria-modal="true" aria-labelledby="pf-popforge-title" aria-describedby="pf-popforge-text">
<button class="pf-close" type="button" aria-label="Close popup">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true"><path d="M1 1l12 12M13 1L1 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
</button>
<div class="pf-body">
<h2 class="pf-title" id="pf-popforge-title">Get the good stuff first</h2>
<p class="pf-text" id="pf-popforge-text">Join 4,200 readers who get one short email each Friday with the best finds, tools and ideas.</p>
</div>
<a class="pf-cta" href="https://example.com/newsletter">Join the list</a>
</div>
</div>
<style>
#pf-popforge {
position: fixed;
inset: 0;
z-index: 99999;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: rgba(8, 7, 6, 0.62);
-webkit-backdrop-filter: blur(3px);
backdrop-filter: blur(3px);
opacity: 0;
visibility: hidden;
transition: opacity 0.25s ease, visibility 0.25s ease;
font-family: inherit;
}
#pf-popforge.is-open {
opacity: 1;
visibility: visible;
}
#pf-popforge .pf-card {
position: relative;
box-sizing: border-box;
width: 100%;
max-width: 420px;
background: #16130F;
color: #F6F1E7;
border-radius: 20px;
padding: 32px;
box-shadow: 0 30px 70px -20px rgba(0, 0, 0, 0.55);
overflow: hidden;
opacity: 0;
transform: translateY(0) scale(1);
transition: transform 0.35s cubic-bezier(0.2, 0.9, 0.2, 1), opacity 0.3s ease;
}
#pf-popforge[data-animation='scale'] .pf-card { transform: scale(0.94); }
#pf-popforge[data-animation='slide'] .pf-card { transform: translateY(32px); }
#pf-popforge.is-open .pf-card {
opacity: 1;
transform: translateY(0) scale(1);
}
#pf-popforge .pf-body { min-width: 0; }
#pf-popforge .pf-media {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 12px;
margin-bottom: 20px;
}
#pf-popforge .pf-title {
margin: 0 0 10px;
font-size: 26px;
line-height: 1.15;
font-weight: 700;
letter-spacing: -0.02em;
}
#pf-popforge .pf-text {
margin: 0 0 22px;
font-size: 15px;
line-height: 1.6;
opacity: 0.78;
}
#pf-popforge .pf-cta {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 13px 22px;
border-radius: 14px;
background: #D9F45C;
color: #111111;
font-size: 15px;
font-weight: 600;
text-decoration: none;
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
#pf-popforge .pf-cta:hover {
transform: translateY(-1px);
box-shadow: 0 10px 24px -12px rgba(0, 0, 0, 0.6);
}
#pf-popforge .pf-close {
position: absolute;
top: 14px;
right: 14px;
display: grid;
place-items: center;
width: 32px;
height: 32px;
padding: 0;
border: 0;
border-radius: 50%;
background: rgba(127, 127, 127, 0.14);
color: inherit;
cursor: pointer;
opacity: 0.7;
transition: opacity 0.15s ease;
}
#pf-popforge .pf-close:hover { opacity: 1; }
#pf-popforge[data-position='bottom-right'] { align-items: flex-end; justify-content: flex-end; }
#pf-popforge[data-position='bottom-center'] { align-items: flex-end; justify-content: center; }
#pf-popforge[data-position='top-bar'] { align-items: flex-start; padding: 0; }
#pf-popforge[data-position='top-bar'] .pf-card {
max-width: 100%;
display: flex;
align-items: center;
gap: 20px;
border-radius: 0 0 20px 20px;
padding: 18px 56px 18px 24px;
}
#pf-popforge[data-position='top-bar'] .pf-body { flex: 1; }
#pf-popforge[data-position='top-bar'] .pf-media { display: none; }
#pf-popforge[data-position='top-bar'] .pf-title { font-size: 18px; margin-bottom: 4px; }
#pf-popforge[data-position='top-bar'] .pf-text { margin: 0; font-size: 14px; }
#pf-popforge[data-position='top-bar'] .pf-cta { flex: none; padding: 11px 18px; }
@media (max-width: 520px) {
#pf-popforge { padding: 16px; }
#pf-popforge .pf-card { padding: 24px; }
#pf-popforge .pf-title { font-size: 22px; }
#pf-popforge[data-position='top-bar'] .pf-card { flex-wrap: wrap; gap: 12px; }
}
@media (prefers-reduced-motion: reduce) {
#pf-popforge, #pf-popforge .pf-card { transition: none; }
}
</style>
<script>
(function () {
var overlay = document.getElementById('pf-popforge');
if (!overlay) return;
var storageKey = 'pf-popforge-seen';
var frequency = 'session';
var lockScroll = true;
var closeOnOverlay = true;
var lastFocus = null;
function alreadySeen() {
if (frequency === 'always') return false;
try {
if (frequency === 'once') return !!localStorage.getItem(storageKey);
return !!sessionStorage.getItem(storageKey);
} catch (error) {
return false;
}
}
function markSeen() {
try {
if (frequency === 'once') localStorage.setItem(storageKey, '1');
if (frequency === 'session') sessionStorage.setItem(storageKey, '1');
} catch (error) {
/* storage can be blocked, the popup still works */
}
}
function openPopup() {
if (alreadySeen() || overlay.classList.contains('is-open')) return;
lastFocus = document.activeElement;
overlay.classList.add('is-open');
overlay.setAttribute('aria-hidden', 'false');
if (lockScroll) document.body.style.overflow = 'hidden';
markSeen();
var focusable = overlay.querySelector('.pf-cta, .pf-close');
if (focusable) focusable.focus({ preventScroll: true });
}
function closePopup() {
overlay.classList.remove('is-open');
overlay.setAttribute('aria-hidden', 'true');
if (lockScroll) document.body.style.overflow = '';
if (lastFocus && lastFocus.focus) lastFocus.focus({ preventScroll: true });
}
overlay.querySelectorAll('.pf-close').forEach(function (button) {
button.addEventListener('click', closePopup);
});
if (closeOnOverlay) {
overlay.addEventListener('click', function (event) {
if (event.target === overlay) closePopup();
});
}
document.addEventListener('keydown', function (event) {
if (event.key === 'Escape') closePopup();
});
if (alreadySeen()) return;
window.setTimeout(openPopup, 4000);
})();
</script>