Basic Modal

Standard Dialog

A centered modal with title, content, and action buttons.

<div class="modal-backdrop">
  <div class="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
    <header class="modal-header">
      <h2 id="modal-title">Modal Title</h2>
      <button class="modal-close" aria-label="Close">×</button>
    </header>
    <div class="modal-body">
      <p>Modal content goes here...</p>
    </div>
    <footer class="modal-footer">
      <button class="btn btn-secondary">Cancel</button>
      <button class="btn btn-primary">Confirm</button>
    </footer>
  </div>
</div>

Modal Sizes

Size Variants

Small for confirmations, medium for forms, large for complex content.

.modal-sm { max-width: 320px; }  /* Confirmations */
.modal-md { max-width: 480px; }  /* Default */
.modal-lg { max-width: 640px; }  /* Complex content */
.modal-xl { max-width: 800px; }  /* Full forms */

Confirmation Dialog

Destructive Action

Use for irreversible actions with clear warning styling.

<div class="modal modal-sm">
  <header class="modal-header">
    <h2>Delete this item?</h2>
  </header>
  <div class="modal-body">
    <p>This action cannot be undone. The item will be permanently removed.</p>
  </div>
  <footer class="modal-footer">
    <button class="btn btn-secondary">Cancel</button>
    <button class="btn btn-error">Delete</button>
  </footer>
</div>

Modal with Form

Form Dialog

Modals containing form inputs for data collection.

<div class="modal modal-md">
  <header class="modal-header">
    <h2>Add New Item</h2>
    <button class="modal-close">×</button>
  </header>
  <div class="modal-body">
    <div class="form-group">
      <label>Name</label>
      <input type="text" class="input" placeholder="Enter name">
    </div>
    <div class="form-group">
      <label>Description</label>
      <textarea class="textarea" rows="3"></textarea>
    </div>
  </div>
  <footer class="modal-footer">
    <button class="btn btn-secondary">Cancel</button>
    <button class="btn btn-primary">Save</button>
  </footer>
</div>

CSS Implementation

/* Backdrop */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: var(--z-modal);
  animation: backdrop-fade-in var(--duration-normal) var(--ease-ease-out);
}

@keyframes backdrop-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Modal */
.modal {
  background: var(--bg-elevated);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 480px;
  max-height: calc(100vh - var(--space-8));
  overflow: hidden;
  display: flex;
  flex-direction: column;
  animation: modal-slide-in var(--duration-slow) var(--ease-spring);
}

@keyframes modal-slide-in {
  from {
    opacity: 0;
    transform: scale(0.95) translateY(10px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

/* Header */
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--border-subtle);
}

.modal-header h2 {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  margin: 0;
}

.modal-close {
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: var(--text-xl);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all var(--duration-fast) var(--ease-ease-out);
}

.modal-close:hover {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

/* Body */
.modal-body {
  padding: var(--space-6);
  overflow-y: auto;
  flex: 1;
}

.modal-body p {
  color: var(--text-secondary);
  line-height: var(--leading-relaxed);
}

/* Footer */
.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--border-subtle);
  background: var(--bg-secondary);
}

/* Sizes */
.modal-sm { max-width: 320px; }
.modal-md { max-width: 480px; }
.modal-lg { max-width: 640px; }
.modal-xl { max-width: 800px; }

/* Glass variant */
.modal-glass {
  background: var(--bg-glass);
  backdrop-filter: blur(var(--glass-blur-heavy));
  border: 1px solid var(--border-glass);
}

Accessibility

Focus Trap

Focus is trapped within the modal. Tab cycles through focusable elements without leaving.

Escape to Close

Pressing Escape dismisses the modal. Click outside (backdrop) also closes it.

ARIA Attributes

Use role="dialog", aria-modal="true", and aria-labelledby for the title.

Focus Restoration

When closed, focus returns to the element that triggered the modal.