JavaScript Popup Modal - Live Demo

Interactive examples of hcg-modal, a small, dependency-free popup modal in vanilla JavaScript. Click the buttons below to try sizes, positions, custom width, scroll modes, animations, auto-close timers, layered stacking, and bring-your-own-box dialogs. Full documentation is available at html-code-generator.com/javascript/modal-popup-library.

Sizes

Show code
hcgModal({ size: 'small', content: '...' }).open();
// size: 'small' | 'medium' | 'large' | 'fullscreen'

Custom width

Show code
hcgModal({ width: 600, content: '...' }).open();    // number -> px
hcgModal({ width: '70%', content: '...' }).open();   // any CSS length

Animated open & close (CSS only)

Animation comes entirely from the .demo-anim CSS class (in this page's <style>) passed via the className option - the modal JS is untouched. It animates in on open and out on close. Requires a browser without reduced motion enabled.

Show code
/* CSS - start state + .hcg-modal--visible end state */
.demo-anim .hcg-modal-dialog {
  opacity: 0; transform: translateY(40px) scale(.96);
  transition: transform .4s, opacity .4s;
}
.demo-anim.hcg-modal--visible .hcg-modal-dialog { opacity: 1; transform: none; }

/* JS - drive the animation purely via className */
hcgModal({ content: '...', className: 'demo-anim' }).open();

Built-in animations

Ship-with-the-library classes passed via className - no extra CSS needed. They use a spring easing curve and honor reduced motion (turn on OS animation effects to see them).

Show code
hcgModal({ content: '...', className: 'hcg-modal--anim-fade'  }).open();
hcgModal({ content: '...', className: 'hcg-modal--anim-slide' }).open();
hcgModal({ content: '...', className: 'hcg-modal--anim-pop'   }).open();
// slide direction follows `position` (top / center / bottom)

Positions

Show code
hcgModal({ position: 'top', content: '...' }).open();
// position: 'center' | 'top' | 'bottom'

Promise result, beforeClose, timer, Enter-to-confirm

Show code
// Promise result - await the clicked button's value
const ok = await hcgModal({
  title: 'Delete item?',
  buttons: [
    { text: 'Cancel', value: false },
    { text: 'Delete', type: 'danger', value: true }
  ]
}).opened();                       // dismissing resolves undefined

// beforeClose veto - return false (or a Promise) to cancel the close
hcgModal({ beforeClose: (reason) => window.confirm('Close?') }).open();

// auto-close timer + progress bar (pauses on hover)
hcgModal({ content: 'Saved', timer: 3000, timerProgressBar: true }).open();

// Enter triggers the primary button
hcgModal({ confirmOnEnter: true, buttons: [
  { text: 'No', value: 'no' },
  { text: 'Yes', type: 'primary', value: 'yes' }
]}).opened();

Large content / scroll modes

Show code
hcgModal({ content: longHtml }).open();                       // default: body scrolls, header/footer pinned
hcgModal({ scrollBody: false, content: longHtml }).open();   // whole dialog scrolls

Close behaviors

Show code
hcgModal({ closeOnBackdrop: false }).open();   // backdrop click won't close
hcgModal({ closeOnEsc: false }).open();        // Escape won't close
hcgModal({ showClose: false }).open();         // no X button

Bring your own box (Option B)

Use an existing HTML box (heading + content + footer) as the modal, instead of the built-in title / buttons options.

Show code
<div id="myBox" style="display:none">
  <div class="box-head">Heading</div>
  <div class="box-body">Content</div>
  <button class="close">Cancel</button>   <!-- auto-wired -->
</div>

const box = document.getElementById('myBox').cloneNode(true);
hcgModal({ box: box }).open();   // box = the whole dialog

Glassmorphism theme

Show code
hcgModal({ content: '...', className: 'hcg-modal--glass' }).open();

Close on back button

Opens with closeOnBackButton: true. Press the browser/mobile Back button (or swipe back) and the modal closes instead of navigating away. Closing it with the X or Esc cleans up the history entry.

Show code
hcgModal({ content: '...', closeOnBackButton: true }).open();

Footer buttons + callbacks

Show code
hcgModal({
  title: 'Delete item?',
  content: '...',
  buttons: [
    { text: 'Cancel', type: 'secondary', onClick: m => m.close() },
    { text: 'Delete', type: 'danger', onClick: m => { /* ... */ m.close(); } }
  ]
}).open();

Layered stacking (A → B → C)

Each layer opens above the previous one. Press Esc (or use the close button) to dismiss them from the top down - C first, then B, then A.

Show code
hcgModal({
  title: 'Layer A',
  buttons: [
    { text: 'Open layer B', type: 'primary', onClick: () => {
      hcgModal({ title: 'Layer B', content: '...' }).open();   // stacks on top
    } },
    { text: 'Close A', type: 'secondary', onClick: m => m.close() }
  ]
}).open();
// Esc / back button close from the top down: C, then B, then A

Tall content to make the page scrollable.