webdevpuneet.com

Maintenance Page with Countdown — HTML CSS JS Snippet

Maintenance Page · Layouts · Plain HTML, CSS & JS · Live preview

CategoryLayouts

Copy & paste

Source Code

<div class="page">
  <div class="bg-grid"></div>
  <div class="content">
    <div class="logo"><div class="logo-icon">⚙️</div></div>
    <div class="status-pill">
      <span class="pulse-dot"></span>
      <span>Scheduled Maintenance</span>
    </div>
    <h1 class="heading">We'll be right back.</h1>
    <p class="sub">We're upgrading our systems to serve you better. This typically takes under 30 minutes.</p>
    <div class="countdown" id="countdown">
      <div class="unit"><span class="num" id="ch">00</span><span class="lbl">Hours</span></div>
      <span class="sep">:</span>
      <div class="unit"><span class="num" id="cm">00</span><span class="lbl">Minutes</span></div>
      <span class="sep">:</span>
      <div class="unit"><span class="num" id="cs">00</span><span class="lbl">Seconds</span></div>
    </div>
    <div class="notify">
      <input class="email-inp" id="notifyEmail" type="email" placeholder="Enter your email" autocomplete="email">
      <button class="notify-btn" onclick="notifyMe()">Notify me</button>
    </div>
    <p class="notify-sub" id="notifyMsg"></p>
    <div class="socials">
      <a class="social-link" href="#">Twitter</a>
      <a class="social-link" href="#">Status Page</a>
      <a class="social-link" href="#">Support</a>
    </div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Live countdown timer targeting a configurable end time
Pulsing amber dot in a status pill communicating active maintenance
Rocking gear logo animation reinforcing the maintenance context
Subtle dot-grid background using CSS linear-gradient with radial mask
Email notification form with validation and disabled-after-submit state
Social/status page link row for self-service updates
Countdown fades when the expected window has elapsed
Full-screen dark layout suitable as a direct HTTP 503 response page

About this UI Snippet

Maintenance Page — Countdown Timer, Status Pill, Email Notify & Grid Background

Screenshot of the Maintenance Page snippet rendered live

A maintenance page (also called a "down for maintenance" or "we'll be right back" page) is a standard need for any production web application. Showing a polished, branded holding page instead of a server error keeps users informed and reduces support ticket volume during planned outages. This snippet provides a complete maintenance page with a dark-themed design, a subtle grid background, an animated status pill, a countdown timer, an email notification sign-up, and social/status links — for a pre-launch variant, see the coming soon hero.

The countdown timer

The timer targets a configurable end time (set 28 minutes from load in the snippet). tick() runs every second, computing the remaining hours, minutes, and seconds by dividing the millisecond diff and taking modulo values. It pads each unit to two digits with padStart(2, '0') for a consistent display width. The timer stops when the diff reaches zero and fades the countdown to indicate the expected window has passed. In production, the target time would come from a server-rendered config variable so the countdown reflects the actual maintenance window.

The status pill and pulse dot

The amber pulse dot uses a CSS keyframe animation cycling between opacity and scale — a lightweight way to convey "in progress" status. The pill's border and background both use rgba values of the brand colour so it reads against any dark background without hardcoding neutrals.

The grid background

The page background uses two overlapping CSS linear-gradient "lines" at 40px spacing to create a dot-grid pattern, masked with a radial gradient so it fades to black at the edges. This technique creates a sophisticated tech aesthetic with no images or SVG. The mask-image radial gradient is the key detail — without it the grid would be uniform and flat.

Email notification capture

The notify form validates the email client-side and shows a confirmation message on submission. In production this would POST to an endpoint that stores the email and sends a "we're back" email when the maintenance window ends. The form is disabled after submission to prevent duplicate entries.

The rocking gear animation

The logo icon uses a CSS keyframe that rotates between −6° and +6°, creating a mechanical rocking motion that reinforces the maintenance concept without requiring an external animation library or lottie file. The animation is subtle enough not to be distracting during what is a tense moment for the user.

Step by step

How to Use

  1. 1
    Set the maintenance end timeChange the target variable from Date.now() + 28 * 60 * 1000 to a specific end time (e.g. new Date("2026-06-16T14:00:00Z")) to reflect your actual maintenance window.
  2. 2
    Update the heading and messageChange the heading and sub-text to match your brand voice and include any relevant details (what system is being updated, why).
  3. 3
    Replace the logoSwap the ⚙️ emoji with your logo SVG or an <img> tag. The logo container already handles sizing and shadow.
  4. 4
    Wire the email formIn notifyMe(), POST the validated email to your API endpoint. Store it and send a notification email when the maintenance concludes.
  5. 5
    Update the social linksReplace the Twitter, Status Page, and Support hrefs with your actual links. The status page link is particularly important during outages.
  6. 6
    Export for your frameworkClick "React" for a component with the countdown in useEffect and useRef. Click "Vue" for a Vue 3 SFC with onMounted and onUnmounted interval cleanup.

Real-world uses

Common Use Cases

Planned maintenance and deployment windows
Serve the maintenance page via your load balancer or CDN during planned database migrations, major releases, or infrastructure upgrades. A countdown timer and a "notify me" capture turn a frustrating downtime into a managed experience that keeps users informed and gives your team a clean window to work.
Database migration or schema change window
When running a zero-downtime migration is not possible (large schema changes, data backfills), take the app offline with this page. Set the countdown to the migration's estimated completion, link to your status page for real-time updates, and capture emails to notify users when the migration completes.
Product launch "coming soon" variant
Repurpose the page as a pre-launch holding page: change the heading to "Launching Soon", swap "Scheduled Maintenance" for "Coming Soon", and use the email form to build a waitlist. The countdown becomes the launch timer, and the grid background gives the page a tech startup aesthetic.
Integrate with your status page and incident system
Read the maintenance end time from your incident management API (PagerDuty, Statuspage.io) and inject it into the page at serve time. Update the countdown target server-side so users always see an accurate remaining estimate even if they refresh the page.
Study the CSS grid-line and mask technique
The background grid is a notable pure-CSS technique: two perpendicular linear-gradient "lines" at the same spacing create a grid pattern, and a radial mask-image fades it to transparent at the edges. This technique transfers to hero sections, card backgrounds, and code editor UIs anywhere a tech-flavoured grid is needed.
503 error page in your web server or CDN config
Configure your web server (nginx, Caddy) or CDN (Cloudflare Pages, AWS CloudFront) to serve the maintenance page as a custom 503 response. This ensures the page appears even when your application server is completely unreachable, rather than the browser's generic error screen.
Related: Hero with Animated Scroll Cue
See the Hero with Animated Scroll Cue for a related heroes pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Replace var target = new Date(Date.now() + 28 * 60 * 1000) with var target = new Date("2026-06-16T15:00:00Z"), using your actual maintenance window end time in ISO 8601 UTC format. All visitors then see the same remaining time regardless of when they load the page, which is the correct behaviour for a shared maintenance window. If your maintenance window is server-configured, inject the end time as a JavaScript variable from your server-side template.

When diff reaches zero, tick() stops calling itself and fades the countdown numbers to 0.4 opacity to signal that the expected window has elapsed. In production you should also add a page-reload after a short delay (e.g., setTimeout(() => location.reload(), 15000)) so users whose page was open during maintenance automatically return to the live site once it comes back up.

In nginx, add error_page 503 /maintenance.html; and return 503; in a location block. In Caddy, use the respond directive with a 503 status and the page HTML as the body, or rewrite to a static HTML file. With Cloudflare, use a Worker that returns the maintenance page with a 503 status when a kill-switch KV key is set. The page should itself be a static file with no backend dependencies so it serves even when your application is completely down.

In a useEffect, set up a setInterval(tick, 1000) that computes remaining time from a target Date and updates a timeLeft state object { h, m, s }. Clear the interval in the useEffect cleanup. The notify form keeps email and submitted in useState; on submit, validate and call your API. Because maintenance pages should work without JavaScript in some configurations, consider a server-rendered version (Next.js getServerSideProps returning the target time as a prop) so the countdown is pre-rendered on the correct value. For the Tailwind version, click "Tailwind" to get the same markup with utility classes instead of a scoped stylesheet.