Error 404

( Error / 404 / Flat / Animated )

A not-found illustration where the zero in 404 breaks into two halves that drift apart, with a spark arcing across the gap.

Live preview and source code for Error 404

44
44
44

A not-found illustration for a 404 page: the zero in the middle of the number is split into two halves that drift apart, with a spark arcing across the gap like a broken connection. The digits are SVG text in the page's own font, so it matches your type rather than looking like a stock graphic, and the accent colour is a prop. Title and description sit underneath and can be replaced or removed.

Installation

Copy the source from the Code tab above into your project as Error404.tsx. The artwork is inline SVG and the copy below it is styled inline, so there is no image to host and no stylesheet to import.

It imports framer-motion for the drift and the spark:

Terminal
npm install framer-motion

Rendered with still, nothing animates, so a static-only copy can drop that import and turn the two motion.path halves of the zero into plain path elements.

Usage

Every prop is optional. size is the rendered width in pixels and the height follows at 60 percent of it:

Example.tsx
import Error404 from "./components/Error404";

export default function Example() {
    return (
        <Error404
            size={300}
            accent="#7c3aed"
            title="Page not found"
            description="The link may be broken, or the page may have moved."
        />
    );
}

Pass title={null} and description={null} for the number on its own, and still to stop the drift and hide the spark.

When to reach for it

The not-found route of a site, where the page needs to say something went missing without looking like a crash. The drifting halves read as a broken link rather than an error.

A dead or expired share link, where the useful message is that the address no longer resolves.

An empty routing state in a dashboard, at a smaller size, sitting above a link back to somewhere real.

When not to

If the server failed. A 500, a timeout or a thrown error is a different message: something on your side broke and retrying may work. This says the address is wrong, which sends the reader looking in the wrong place.

If a search or filter returned nothing. That is a zero state, not a missing page. Empty Search is the one for that.

If you need the number to be selectable text. The digits are SVG text inside an image role, so they cannot be copied and are not part of the page's text content.

Accessibility

The SVG carries role="img" and a label naming the page as not found, so it is announced once as a picture and the loose digits inside it never reach the reading order individually. The title and description below are plain text and read normally.

That label is a literal string in the source. Changing title or translating the page does not update it, so edit the aria-label in the copied file when the language changes.

The drift and spark loop forever and do not check prefers-reduced-motion. Pass still from your own media query check if you honour that setting.

Notes

The digits use font-family: inherit, which is what makes them match the page, and also means the spacing depends on your font. The two 4s are positioned at fixed coordinates either side of the zero, so a very wide typeface can crowd the gap. Check it once with your own font before shipping.

The gradient in <defs> is declared with the id e404-num. Two of these on one page would duplicate that id, so rename it in the copied file if that happens.

still hides the spark rather than freezing it mid-arc, so the still version is the number with a clean gap.

The digit colours are a fixed dark gradient built for a light background. On a dark page the accent still works but the 4s need recolouring in the source.