Home / Snippets / UI /

Decorative border

Create a decorative multi-layer border using outline + outline-offset and box-shadow to add visual depth to cards and buttons without extra markup.

1 — outline + outline-offset gap
Outline gap effect
A visible gap between element edge and outline using outline-offset.
2 — double box-shadow border
Double ring effect
Two concentric rings built with stacked box-shadow values.
3 — layered glow border
Layered glow
Multiple box-shadow layers fade outward for a soft halo effect.
Widely Supported
uino-js

Quick implementation

/* Pattern 1: outline + outline-offset gap */
.card--outline-gap {
  outline: 2px solid oklch(0.52 0.22 265);
  outline-offset: 4px; /* creates visible gap */
  border-radius: 0.5rem;
}

/* Pattern 2: double box-shadow ring */
.card--double-ring {
  box-shadow:
    0 0 0 1px oklch(0.52 0.22 265),        /* inner ring */
    0 0 0 4px oklch(0.13 0.02 260),        /* gap (matches bg) */
    0 0 0 6px oklch(0.52 0.22 265 / 0.4); /* outer ring */
  border-radius: 0.5rem;
}

/* Pattern 3: layered glow border */
.card--glow {
  box-shadow:
    0 0 0 1px oklch(0.72 0.19 265 / 0.8),
    0 0 0 3px oklch(0.52 0.22 265 / 0.3),
    0 0 0 5px oklch(0.72 0.19 265 / 0.15),
    0 4px 16px oklch(0.52 0.22 265 / 0.2);
  border-radius: 0.5rem;
}

/* Keep focus ring visible — don't override outline on focusable elements */
.card--outline-gap:focus-visible {
  outline-color: oklch(0.9 0.15 90); /* distinct focus color */
  outline-offset: 6px;
}

Prompt this to your LLM

Includes role, constraints, pattern variants, and edge cases to handle.

You are a senior frontend engineer explaining decorative border
techniques in CSS using outline-offset and box-shadow.

Goal: Create three decorative border patterns for cards and buttons
that add visual depth without extra markup or pseudo-elements.
Pattern A: outline + outline-offset to create a visible gap between
the element edge and a surrounding ring.
Pattern B: multiple box-shadow values to simulate a double-ring
border (inner ring, gap layer, outer ring).
Pattern C: layered box-shadow values that fade outward for a soft
halo or glow effect around the element.

Technical constraints:
- No extra wrapper elements or pseudo-elements — pure CSS on the
  element itself.
- Use oklch() for all color values — no hex or rgba.
- For elements that may receive keyboard focus, outline must not
  interfere with the visible focus indicator. Show how to use
  a distinct outline-color on :focus-visible so the decorative
  outline and the focus ring don't visually collide.
- box-shadow does not affect layout flow (unlike border/outline
  in some cases) — note this as an advantage.
- All three patterns must work on elements with border-radius.

Edge cases to handle:
- The double-ring pattern fakes a gap by matching the gap layer
  color to the page background — this breaks on non-solid
  backgrounds (gradients, images). Explain the limitation.
- outline-offset can be negative, pulling the outline inside the
  element's border box — show an inset ring variant.
- When stacking many box-shadow layers, rendering performance can
  degrade on low-end devices — recommend limiting to 3-4 layers
  for decorative use.

Return CSS only.

Outline vs border for decoration

The border property takes up space in the layout — it affects the element's box model and can shift surrounding content if you add or remove it. The outline property, by contrast, is drawn outside the border box and does not affect layout flow at all. This makes outline a cleaner choice for purely decorative rings that you want to add or remove without reflowing the page.

The key advantage of outline for decoration is outline-offset. A positive value pushes the outline away from the element's edge, creating a visible gap — like a picture frame with a mat board. A negative value pulls the outline inside the element's border box for an inset ring effect. Neither value affects layout.

One caveat: outline is also the default focus indicator for keyboard navigation. If you use outline for decoration on interactive elements (buttons, links, cards with tabindex), always pair it with a distinct :focus-visible rule so keyboard users still get a clearly visible focus ring.

outline-offset gap effect

Setting outline-offset: 4px on a card creates a 4-pixel gap between the card's edge and the surrounding outline. This works on any element shape — including elements with border-radius, where the outline follows the rounded corners. The gap reads as intentional whitespace, giving the card a framed, elevated appearance without any extra HTML elements.

For interactive cards, combine the decorative outline with a hover state: increase the outline-offset slightly on :hover to create a subtle "lift" animation when paired with a CSS transition. This adds a polished interactive feel with just two CSS properties.

Box-shadow layered borders

The box-shadow property accepts a comma-separated list of shadow values, each rendered as a separate layer. By using 0 0 0 Npx color (zero blur, zero offset, only spread), you get a solid ring at exactly N pixels from the element's edge. Stacking two of these with a gap layer in between — where the gap layer matches the page background color — creates the illusion of a double border.

The layered glow variant takes this further: each successive shadow layer has a larger spread and lower opacity, creating a soft halo that diffuses outward. This works well for primary action buttons or highlighted cards where you want to draw the eye without a hard-edged ring.

One important limitation: the fake-gap trick in the double-ring pattern relies on the gap color matching the page background. On non-solid backgrounds — such as gradient page backgrounds, image backgrounds, or transparent elements — the gap will be visible as a colored ring rather than an invisible gap. For those cases, the outline-offset approach is more robust since the browser handles the actual gap rendering.

When to use each approach

Use outline + outline-offset when: you need a gap effect on non-solid backgrounds, you want the simplest possible CSS, the element is interactive (easier to manage focus styles), or you need the outline to animate its offset on hover.

Use box-shadow layered borders when: you want a glow or halo that fades outward, you need more than two rings, you want to combine a decorative border with a drop shadow in a single property, or you need the decorative border to be invisible to the layout (box-shadow never affects layout, while outline can in rare edge cases with overflow).

Both approaches work in all modern browsers with no vendor prefixes. For the widest compatibility, box-shadow has slightly older browser support, but both are safe to use in production today.