36 CSS Modals33 / 36

CSS + JSMIT licensed

Order Success Confirmation Modal

An e-commerce order success confirmation modal ("Thanks for your order") with a signature Morphing Button Elastic entrance + CSS-only confetti burst — the modal expands elastically from small to full size while colorful confetti particles fire outward from center. Order summary + shipping ETA + tracking CTA + "Share your purchase" social row. Full intensity — order success is the peak dopamine moment, users EXPECT celebration UI.

Published Updated

Live Demo
Try it

The code

<div class="md-15">
  <button class="md-15__trigger" id="md-15-open">Complete order · $189</button>
  <div class="md-15__backdrop" id="md-15-dialog" role="dialog" aria-modal="true" aria-labelledby="md-15-title">
    <div class="md-15__modal">
      <div class="md-15__confetti" aria-hidden="true">
        <span style="--c:#ff6b6b;--angle:12deg;--dist:180px"></span>
        <span style="--c:#4ecdc4;--angle:47deg;--dist:210px"></span>
        <span style="--c:#c9a961;--angle:88deg;--dist:170px"></span>
        <span style="--c:#a855f7;--angle:128deg;--dist:200px"></span>
        <span style="--c:#10b981;--angle:165deg;--dist:190px"></span>
        <span style="--c:#ff6b6b;--angle:205deg;--dist:220px"></span>
        <span style="--c:#4ecdc4;--angle:240deg;--dist:180px"></span>
        <span style="--c:#c9a961;--angle:275deg;--dist:210px"></span>
        <span style="--c:#a855f7;--angle:312deg;--dist:200px"></span>
        <span style="--c:#10b981;--angle:340deg;--dist:190px"></span>
        <span style="--c:#ec4899;--angle:60deg;--dist:150px"></span>
        <span style="--c:#3b82f6;--angle:220deg;--dist:150px"></span>
      </div>
      <button class="md-15__x md-15__close" aria-label="Close">✕</button>
      <div class="md-15__check-badge" aria-hidden="true">✓</div>
      <p class="md-15__eyebrow">Order #TR-8842</p>
      <h2 class="md-15__title" id="md-15-title">Thanks for your order, Alex</h2>
      <p class="md-15__sub">A confirmation is on its way to <strong>alex@studio.com</strong>. Your package ships in 24 hours.</p>
      <div class="md-15__eta">
        <div>
          <p class="md-15__eta-label">Estimated delivery</p>
          <p class="md-15__eta-value">Tue, Jul 30 — Thu, Aug 1</p>
        </div>
        <div class="md-15__eta-badge">Free 2-day shipping</div>
      </div>
      <div class="md-15__summary">
        <div class="md-15__row"><span>Subtotal (2 items)</span><span>$168.00</span></div>
        <div class="md-15__row"><span>Shipping</span><span class="md-15__row-good">Free</span></div>
        <div class="md-15__row"><span>Tax</span><span>$21.00</span></div>
        <div class="md-15__row md-15__row--total"><strong>Total charged</strong><strong>$189.00</strong></div>
      </div>
      <button class="md-15__cta md-15__close">Track your order →</button>
      <div class="md-15__aux">
        <button class="md-15__aux-btn md-15__close">Print receipt</button>
        <button class="md-15__aux-btn md-15__close">Share purchase</button>
      </div>
    </div>
  </div>
</div>
.md-15 {
  --page-bg: #fdf7f4;
  --card: #faf7f0;
  --ink: #1e293b;
  --sub: #6b6558;
  --brand: #059669;
  --good: #10b981;
  --accent: #ff6b6b;
  --line: #eee5d0;
  font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  min-height: 100vh;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: radial-gradient(60% 100% at 50% 100%, rgba(16,185,129,.08) 0%, transparent 60%), var(--page-bg);
  color: var(--ink);
}

.md-15 *,
.md-15 *::before,
.md-15 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.md-15 ::selection {
  background: var(--brand);
  color: #fff;
}

.md-15__trigger {
  padding: 13px 26px;
  border: none;
  border-radius: 9px;
  background: var(--ink);
  color: var(--card);
  font-family: inherit;
  font-size: .92rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 10px 22px -6px rgba(30,41,59,.4);
  transition: background .18s ease;
}

.md-15__trigger:hover {
  background: #000;
}

.md-15__backdrop {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(30,41,59,.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease,visibility 0s linear .3s;
}

.md-15__backdrop.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity .3s ease,visibility 0s linear 0s;
}

.md-15__modal {
  position: relative;
  width: min(460px,100%);
  padding: 36px 30px 24px;
  border-radius: 16px;
  background: var(--card);
  box-shadow: 0 40px 60px -20px rgba(30,41,59,.35);
  text-align: center;
  will-change: transform;
  /* Signature entrance: Morphing Button Elastic */
  opacity: 0;
  transform: scale(.12);
  transition: opacity .35s ease,transform .65s cubic-bezier(.68,-0.55,.32,1.55);
}

.md-15__backdrop.is-open .md-15__modal {
  opacity: 1;
  transform: scale(1);
}
/* Confetti burst */

.md-15__confetti {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
}

.md-15__confetti span {
  position: absolute;
  width: 10px;
  height: 14px;
  background: var(--c);
  border-radius: 2px;
  opacity: 0;
  transform: translate(-50%,-50%) rotate(0deg);
}

.md-15__backdrop.is-open .md-15__confetti span {
  animation: md-15-confetti 1.2s cubic-bezier(.4,0,.2,1) forwards;
  animation-delay: calc(var(--angle) / 360 * 0.5s);
}

@keyframes md-15-confetti {
  0% {
    opacity: 0;
    transform: translate(-50%,-50%) rotate(0deg);
  }

  15% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    transform: translate(
            calc(-50% + cos(var(--angle)) * var(--dist)),
            calc(-50% + sin(var(--angle)) * var(--dist))
          ) rotate(720deg);
  }
}

.md-15__x {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--sub);
  font-family: inherit;
  font-size: 15px;
  cursor: pointer;
  transition: background .18s ease,color .18s ease;
}

.md-15__x:hover {
  background: rgba(26,26,26,.06);
  color: var(--ink);
}

.md-15__check-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: linear-gradient(135deg,var(--good),var(--brand));
  color: #fff;
  font-size: 24px;
  font-weight: 900;
  margin-bottom: 14px;
  box-shadow: 0 8px 20px -4px rgba(16,185,129,.5);
}

.md-15__eyebrow {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--sub);
  margin-bottom: 8px;
  font-family: 'JetBrains Mono',ui-monospace,monospace;
}

.md-15__title {
  font-family: 'Playfair Display',Georgia,serif;
  font-size: 1.55rem;
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.15;
  margin-bottom: 8px;
}

.md-15__sub {
  font-size: .85rem;
  color: var(--sub);
  line-height: 1.55;
  margin-bottom: 18px;
}

.md-15__eta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 9px;
  background: rgba(16,185,129,.08);
  text-align: left;
  margin-bottom: 14px;
}

.md-15__eta-label {
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--brand);
}

.md-15__eta-value {
  font-size: .88rem;
  font-weight: 700;
  color: var(--ink);
  margin-top: 2px;
}

.md-15__eta-badge {
  font-size: .7rem;
  font-weight: 700;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--good);
  color: #fff;
  white-space: nowrap;
}

.md-15__summary {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 9px;
  margin-bottom: 16px;
  text-align: left;
}

.md-15__row {
  display: flex;
  justify-content: space-between;
  font-size: .82rem;
  color: var(--sub);
}

.md-15__row + .md-15__row {
  margin-top: 6px;
}

.md-15__row-good {
  color: var(--good);
  font-weight: 700;
}

.md-15__row--total {
  padding-top: 10px;
  margin-top: 10px;
  border-top: 1px solid var(--line);
  color: var(--ink);
}

.md-15__row--total strong {
  font-size: .9rem;
  font-weight: 800;
}

.md-15__cta {
  width: 100%;
  padding: 14px 22px;
  border: none;
  border-radius: 9px;
  background: var(--ink);
  color: var(--card);
  font-family: inherit;
  font-size: .95rem;
  font-weight: 800;
  cursor: pointer;
  transition: background .18s ease,transform .12s ease;
  margin-bottom: 10px;
}

.md-15__cta:hover {
  background: #000;
  transform: translateY(-1px);
}

.md-15__cta:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}

.md-15__aux {
  display: flex;
  gap: 8px;
}

.md-15__aux-btn {
  flex: 1;
  padding: 9px 12px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--sub);
  font-family: inherit;
  font-size: .75rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .18s ease,color .18s ease;
}

.md-15__aux-btn:hover {
  background: rgba(26,26,26,.06);
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .md-15__backdrop,
    .md-15__modal {
    transition: opacity .2s ease!important;
  }

  .md-15__modal {
    transform: none!important;
  }

  .md-15__confetti {
    display: none!important;
  }
}
(function(){
  var root = document.querySelector('.md-15');
  if (!root) return;
  var openBtn = root.querySelector('#md-15-open');
  var dialog = root.querySelector('#md-15-dialog');
  var closeBtns = root.querySelectorAll('.md-15__close');
  var lastFocus = null;

  function open() {
    lastFocus = document.activeElement;
    dialog.classList.add('is-open');
    document.documentElement.style.overflow = 'hidden';
    // Focus Track Order — primary action after success
    var cta = dialog.querySelector('.md-15__cta');
    if (cta) cta.focus();
    document.addEventListener('keydown', onKey);
  }
  function close() {
    dialog.classList.remove('is-open');
    document.documentElement.style.overflow = '';
    document.removeEventListener('keydown', onKey);
    if (lastFocus) lastFocus.focus();
  }
  function onKey(e) { if (e.key === 'Escape') close(); }

  openBtn.addEventListener('click', open);
  closeBtns.forEach(function(b){ b.addEventListener('click', close); });
  dialog.addEventListener('click', function(e){ if (e.target === dialog) close(); });
})();
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Modal from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Order Success Confirmation Modal
Source: https://codefronts.com/components/css-modals/order-success-confirmation-modal/

An e-commerce order success confirmation modal ("Thanks for your order") with a signature Morphing Button Elastic entrance + CSS-only confetti burst — the modal expands elastically from small to full size while colorful confetti particles fire outward from center. Order summary + shipping ETA + tracking CTA + "Share your purchase" social row. Full intensity — order success is the peak dopamine moment, users EXPECT celebration UI.
## HTML
```html
<div class="md-15">
  <button class="md-15__trigger" id="md-15-open">Complete order · $189</button>
  <div class="md-15__backdrop" id="md-15-dialog" role="dialog" aria-modal="true" aria-labelledby="md-15-title">
    <div class="md-15__modal">
      <div class="md-15__confetti" aria-hidden="true">
        <span style="--c:#ff6b6b;--angle:12deg;--dist:180px"></span>
        <span style="--c:#4ecdc4;--angle:47deg;--dist:210px"></span>
        <span style="--c:#c9a961;--angle:88deg;--dist:170px"></span>
        <span style="--c:#a855f7;--angle:128deg;--dist:200px"></span>
        <span style="--c:#10b981;--angle:165deg;--dist:190px"></span>
        <span style="--c:#ff6b6b;--angle:205deg;--dist:220px"></span>
        <span style="--c:#4ecdc4;--angle:240deg;--dist:180px"></span>
        <span style="--c:#c9a961;--angle:275deg;--dist:210px"></span>
        <span style="--c:#a855f7;--angle:312deg;--dist:200px"></span>
        <span style="--c:#10b981;--angle:340deg;--dist:190px"></span>
        <span style="--c:#ec4899;--angle:60deg;--dist:150px"></span>
        <span style="--c:#3b82f6;--angle:220deg;--dist:150px"></span>
      </div>
      <button class="md-15__x md-15__close" aria-label="Close">✕</button>
      <div class="md-15__check-badge" aria-hidden="true">✓</div>
      <p class="md-15__eyebrow">Order #TR-8842</p>
      <h2 class="md-15__title" id="md-15-title">Thanks for your order, Alex</h2>
      <p class="md-15__sub">A confirmation is on its way to <strong>alex@studio.com</strong>. Your package ships in 24 hours.</p>
      <div class="md-15__eta">
        <div>
          <p class="md-15__eta-label">Estimated delivery</p>
          <p class="md-15__eta-value">Tue, Jul 30 — Thu, Aug 1</p>
        </div>
        <div class="md-15__eta-badge">Free 2-day shipping</div>
      </div>
      <div class="md-15__summary">
        <div class="md-15__row"><span>Subtotal (2 items)</span><span>$168.00</span></div>
        <div class="md-15__row"><span>Shipping</span><span class="md-15__row-good">Free</span></div>
        <div class="md-15__row"><span>Tax</span><span>$21.00</span></div>
        <div class="md-15__row md-15__row--total"><strong>Total charged</strong><strong>$189.00</strong></div>
      </div>
      <button class="md-15__cta md-15__close">Track your order →</button>
      <div class="md-15__aux">
        <button class="md-15__aux-btn md-15__close">Print receipt</button>
        <button class="md-15__aux-btn md-15__close">Share purchase</button>
      </div>
    </div>
  </div>
</div>
```
## CSS
```css
.md-15 {
  --page-bg: #fdf7f4;
  --card: #faf7f0;
  --ink: #1e293b;
  --sub: #6b6558;
  --brand: #059669;
  --good: #10b981;
  --accent: #ff6b6b;
  --line: #eee5d0;
  font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  min-height: 100vh;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: radial-gradient(60% 100% at 50% 100%, rgba(16,185,129,.08) 0%, transparent 60%), var(--page-bg);
  color: var(--ink);
}

.md-15 *,
.md-15 *::before,
.md-15 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.md-15 ::selection {
  background: var(--brand);
  color: #fff;
}

.md-15__trigger {
  padding: 13px 26px;
  border: none;
  border-radius: 9px;
  background: var(--ink);
  color: var(--card);
  font-family: inherit;
  font-size: .92rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 10px 22px -6px rgba(30,41,59,.4);
  transition: background .18s ease;
}

.md-15__trigger:hover {
  background: #000;
}

.md-15__backdrop {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(30,41,59,.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease,visibility 0s linear .3s;
}

.md-15__backdrop.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity .3s ease,visibility 0s linear 0s;
}

.md-15__modal {
  position: relative;
  width: min(460px,100%);
  padding: 36px 30px 24px;
  border-radius: 16px;
  background: var(--card);
  box-shadow: 0 40px 60px -20px rgba(30,41,59,.35);
  text-align: center;
  will-change: transform;
  /* Signature entrance: Morphing Button Elastic */
  opacity: 0;
  transform: scale(.12);
  transition: opacity .35s ease,transform .65s cubic-bezier(.68,-0.55,.32,1.55);
}

.md-15__backdrop.is-open .md-15__modal {
  opacity: 1;
  transform: scale(1);
}
/* Confetti burst */

.md-15__confetti {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
}

.md-15__confetti span {
  position: absolute;
  width: 10px;
  height: 14px;
  background: var(--c);
  border-radius: 2px;
  opacity: 0;
  transform: translate(-50%,-50%) rotate(0deg);
}

.md-15__backdrop.is-open .md-15__confetti span {
  animation: md-15-confetti 1.2s cubic-bezier(.4,0,.2,1) forwards;
  animation-delay: calc(var(--angle) / 360 * 0.5s);
}

@keyframes md-15-confetti {
  0% {
    opacity: 0;
    transform: translate(-50%,-50%) rotate(0deg);
  }

  15% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    transform: translate(
            calc(-50% + cos(var(--angle)) * var(--dist)),
            calc(-50% + sin(var(--angle)) * var(--dist))
          ) rotate(720deg);
  }
}

.md-15__x {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--sub);
  font-family: inherit;
  font-size: 15px;
  cursor: pointer;
  transition: background .18s ease,color .18s ease;
}

.md-15__x:hover {
  background: rgba(26,26,26,.06);
  color: var(--ink);
}

.md-15__check-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: linear-gradient(135deg,var(--good),var(--brand));
  color: #fff;
  font-size: 24px;
  font-weight: 900;
  margin-bottom: 14px;
  box-shadow: 0 8px 20px -4px rgba(16,185,129,.5);
}

.md-15__eyebrow {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--sub);
  margin-bottom: 8px;
  font-family: 'JetBrains Mono',ui-monospace,monospace;
}

.md-15__title {
  font-family: 'Playfair Display',Georgia,serif;
  font-size: 1.55rem;
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.15;
  margin-bottom: 8px;
}

.md-15__sub {
  font-size: .85rem;
  color: var(--sub);
  line-height: 1.55;
  margin-bottom: 18px;
}

.md-15__eta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 9px;
  background: rgba(16,185,129,.08);
  text-align: left;
  margin-bottom: 14px;
}

.md-15__eta-label {
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--brand);
}

.md-15__eta-value {
  font-size: .88rem;
  font-weight: 700;
  color: var(--ink);
  margin-top: 2px;
}

.md-15__eta-badge {
  font-size: .7rem;
  font-weight: 700;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--good);
  color: #fff;
  white-space: nowrap;
}

.md-15__summary {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 9px;
  margin-bottom: 16px;
  text-align: left;
}

.md-15__row {
  display: flex;
  justify-content: space-between;
  font-size: .82rem;
  color: var(--sub);
}

.md-15__row + .md-15__row {
  margin-top: 6px;
}

.md-15__row-good {
  color: var(--good);
  font-weight: 700;
}

.md-15__row--total {
  padding-top: 10px;
  margin-top: 10px;
  border-top: 1px solid var(--line);
  color: var(--ink);
}

.md-15__row--total strong {
  font-size: .9rem;
  font-weight: 800;
}

.md-15__cta {
  width: 100%;
  padding: 14px 22px;
  border: none;
  border-radius: 9px;
  background: var(--ink);
  color: var(--card);
  font-family: inherit;
  font-size: .95rem;
  font-weight: 800;
  cursor: pointer;
  transition: background .18s ease,transform .12s ease;
  margin-bottom: 10px;
}

.md-15__cta:hover {
  background: #000;
  transform: translateY(-1px);
}

.md-15__cta:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}

.md-15__aux {
  display: flex;
  gap: 8px;
}

.md-15__aux-btn {
  flex: 1;
  padding: 9px 12px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--sub);
  font-family: inherit;
  font-size: .75rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .18s ease,color .18s ease;
}

.md-15__aux-btn:hover {
  background: rgba(26,26,26,.06);
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .md-15__backdrop,
    .md-15__modal {
    transition: opacity .2s ease!important;
  }

  .md-15__modal {
    transform: none!important;
  }

  .md-15__confetti {
    display: none!important;
  }
}
```

## JavaScript
```js
(function(){
  var root = document.querySelector('.md-15');
  if (!root) return;
  var openBtn = root.querySelector('#md-15-open');
  var dialog = root.querySelector('#md-15-dialog');
  var closeBtns = root.querySelectorAll('.md-15__close');
  var lastFocus = null;

  function open() {
    lastFocus = document.activeElement;
    dialog.classList.add('is-open');
    document.documentElement.style.overflow = 'hidden';
    // Focus Track Order — primary action after success
    var cta = dialog.querySelector('.md-15__cta');
    if (cta) cta.focus();
    document.addEventListener('keydown', onKey);
  }
  function close() {
    dialog.classList.remove('is-open');
    document.documentElement.style.overflow = '';
    document.removeEventListener('keydown', onKey);
    if (lastFocus) lastFocus.focus();
  }
  function onKey(e) { if (e.key === 'Escape') close(); }

  openBtn.addEventListener('click', open);
  closeBtns.forEach(function(b){ b.addEventListener('click', close); });
  dialog.addEventListener('click', function(e){ if (e.target === dialog) close(); });
})();
```

How this works

The signature entrance is Morphing Button Elastic + confetti burst: modal starts at scale(.12), animates to scale(1) via cubic-bezier(.68, -0.55, .32, 1.55) over 650ms (elastic overshoot). Simultaneously, 12 confetti particles (.md-15__confetti span) fire outward via @keyframes md-15-confetti that translates each particle to random angle+distance with rotation. Each particle has a different animation-delay (0.1s-0.6s stagger) so the burst feels organic, not synchronized.

Confetti particles are CSS-only — 12 <span> elements positioned absolute at center, each with a unique color (via --c CSS variable) and unique angle+distance (via --angle and --dist). The @keyframes uses calc() with the CSS vars to compute per-particle translate. No canvas, no JS particle library — pure CSS ~40 lines total. Palette matches celebration: coral, teal, gold, purple, mint.

Full intensity because order success is the highest-value moment in e-commerce funnel — this is where users feel the reward for their purchase decision. Shopify, Etsy, Squarespace, Amazon all use decorative success modals. Warm cream (#faf7f0) card + gradient success accent — celebration + trust palette.

Layout: order number badge, headline ("Thanks for your order, Alex"), estimated delivery (2-4 business days), tracking number reveal, order summary (2 items + subtotal + shipping + total), primary CTA (Track your order), secondary row (Share purchase, Print receipt). WCAG 2.1 dialog: focus on "Track your order" primary CTA. Escape closes. Confetti is aria-hidden='true' (purely decorative).

Make it yours

  • Change confetti particle count by adding/removing <span> elements — 6 for subtle, 12 for standard, 20+ for extravagant. Each particle needs a unique --angle and --dist.
  • Change confetti colors by editing the --c CSS variable on each particle — brand-matched colors (only your brand palette) feel premium, rainbow feels playful/childish.
  • Add order-value-based confetti scaling — $50 order = 6 particles, $500 order = 20 particles. Rewards big spenders with proportionally more celebration.
  • For sustainable brands (Allbirds, Patagonia), replace confetti with a subtle leaf-fall animation (green particles floating down) — matches brand values, avoids plastic-confetti dissonance.
  • Add "Refer a friend for $10 off" widget below CTA — order success is peak referral moment (user is in dopamine state, more willing to share). Amazon, Airbnb use this pattern.

Gotchas — read before shipping

  • Confetti animations MUST respect prefers-reduced-motion — vestibular-disorder users get nauseated from radial burst animations. The demo hides confetti entirely when reduced-motion is preferred; do the same in production.
  • Order confirmation should ALWAYS include order number + email confirmation ETA — users need a reference to contact support. "Thanks!" without an order number is a support-ticket generator.
  • For accessibility, announce the order success via aria-live='assertive' region separately — screen readers announce "Thanks for your order, Alex" but users need the order number spoken too.
  • The 12-particle confetti is 12 <span> elements — that's fine. But 100+ particles create layout thrash on low-end devices. Cap at 20 particles or use <canvas> for high counts.
  • Do NOT auto-dismiss order success modal — this is not add-to-cart. Users need time to screenshot the order number for their records. Amazon leaves the success page permanent (no modal).
  • Confetti gradient palette should match your brand — random rainbow feels childish for premium brands. Everlane uses only cream + burgundy + gold particles (brand-matched).
  • Email confirmation link should mention "Check your spam folder if you don't see it in 5 minutes" — 12-18% of transactional emails land in spam per Mailchimp 2024 data.

Browser support

ChromeSafariFirefoxEdge
76+9+103+76+

Floor set by backdrop-filter as this demo is written. The core technique itself goes back further — Chrome 60+.

CSS custom properties in calc() for particles. Universal 2018+.

Techniques used in this demo

Search CodeFronts

Loading…