Skip to content

Instantly share code, notes, and snippets.

@greggman
Created September 2, 2025 07:05
Show Gist options
  • Save greggman/b41bcb37b0eaaa93e29c612242bf6674 to your computer and use it in GitHub Desktop.
Save greggman/b41bcb37b0eaaa93e29c612242bf6674 to your computer and use it in GitHub Desktop.
HTML Dialog with header, footer, and scrolling content

HTML Dialog with header, footer, and scrolling content

view on jsgist

/* ---- Page baseline ---- */
:root {
--overlay-bg: rgba(0, 0, 0, 0.55);
--surface: #fff;
--text: #111;
--radius: 16px;
--shadow: 0 10px 30px rgba(0,0,0,0.25);
--gap: 16px;
--border: 1px solid #e5e7eb;
}
html, body {
height: 100%;
}
body {
margin: 0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
color: var(--text);
background: #f7f7f8;
}
main {
max-width: 60rem;
margin: 4rem auto;
padding: 0 1rem;
}
/* ---- Modal overlay ---- */
.modal-overlay {
position: fixed;
inset: 0;
background: var(--overlay-bg);
display: grid;
place-items: center;
/* make sure the overlay captures all pointer/keyboard navigation */
z-index: 9999;
}
/* ---- Dialog ---- */
.dialog {
background: var(--surface);
color: var(--text);
max-width: 80vw; /* <= your requirement */
max-height: 80vh; /* <= your requirement */
width: min(720px, 80vw);
border-radius: var(--radius);
box-shadow: var(--shadow);
border: var(--border);
/* Keep footer visible while body scrolls */
display: flex;
flex-direction: column;
/* Prevent the whole dialog from scrolling; only body scrolls */
overflow: hidden;
}
.dialog__header {
padding: calc(var(--gap) + 2px) var(--gap);
border-bottom: var(--border);
font-size: 1.125rem;
font-weight: 600;
}
.dialog__body {
padding: var(--gap);
overflow: auto; /* <== only the body scrolls */
flex: 1 1 auto; /* <== take remaining space */
}
.dialog__footer {
padding: var(--gap);
border-top: var(--border);
display: flex;
justify-content: flex-end;
gap: 8px;
}
.btn {
appearance: none;
border: 1px solid #d1d5db;
background: #f9fafb;
padding: 10px 16px;
border-radius: 12px;
font-weight: 600;
cursor: pointer;
}
.btn.primary {
background: #111827;
color: white;
border-color: #111827;
}
/* Optional: prevent body from scrolling while modal is open */
body.modal-open {
overflow: hidden;
touch-action: none;
}
/* Demo flourish: long content */
.demo-block {
height: 1200px;
background: linear-gradient(#fff, #f0f4ff);
border-radius: 8px;
border: 1px dashed #c7d2fe;
}
<!-- Everything on the page -->
<main id="page-content" inert>
<h1>Example Page Content</h1>
<p>The modal is open; this content is inert (unfocusable and non-interactive).</p>
</main>
<!-- Modal (accessible structure) -->
<div class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<section class="dialog" role="document" tabindex="-1">
<header class="dialog__header" id="dialog-title">Example Dialog Title</header>
<div class="dialog__body" id="dialog-desc">
<p>
This section scrolls if it’s too tall, while the OK button below stays anchored
at the bottom of the dialog.
</p>
<p>
Max width/height are 80% of the viewport. Resize your window to see the behavior.
</p>
<!-- demo filler to force overflow -->
<div class="demo-block"></div>
</div>
<footer class="dialog__footer">
<button class="btn">Cancel</button>
<button class="btn primary">OK</button>
</footer>
</section>
</div>
<!--
Notes:
- In a real app, when you close the dialog:
* remove `inert` from #page-content,
* remove `modal-open` from <body>,
* hide/remove the .modal-overlay.
- The `inert` attribute is supported in all modern evergreen browsers.
It prevents focus/interaction on the covered page while the modal is open.
-->
\
/*bug-in-github-api-content-can-not-be-empty*/
{"name":"HTML Dialog with header, footer, and scrolling content","settings":{},"filenames":["index.html","index.css","index.js"]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment