Toggle Sidebar B
AppearanceLight & dark mode D

Border Beam

Animated glow that wraps any element. A beam travels around the border (rotate family) or the glow breathes in place (pulse family). Vue port of border-beam by Jakub Antalik, MIT licensed.

Default

Wrap any element. The beam sizes itself to the wrapper and picks up the border radius of the first child, so a rounded card needs no extra configuration.

Dark previewReplay preview

Build anything...

Rotate family

A beam travels around the element. md is the full border glow, sm is tuned for compact controls, and line lights only the bottom edge, which suits inputs and search bars.

Dark previewReplay preview
Build anything...
AgentAuto
Search

Pulse family

The glow breathes instead of travelling. pulse-inner stays contained inside the border, pulse-outside blooms past the element as a halo, so give it room to spill and an opaque child to bloom behind.

Dark previewReplay preview

Working...

  • Generate color palettes
  • Recommend font pairings
  • Create layout templates
  • Build section engine
Subscribe
Build anything...

Color variants

Four palettes. All of them drift through a hue cycle except mono, which pins its colors.

Dark previewReplay preview
colorful
mono
ocean
sunset

Strength

strength scales the whole effect between 0 and 1. It touches only the beam, glow and bloom layers, never the wrapped content.

Dark previewReplay preview
strength 1
strength 0.7
strength 0.35

Theme

The palette adapts to the substrate it sits on. auto follows the nearest data-theme attribute or dark/light class and updates live when the page theme flips. Pin it with light or dark when the element sits on a fixed surface.

Dark previewReplay preview
theme="light"
theme="dark"
theme="auto"

Play and pause

Toggling active fades the effect in and out rather than cutting it. The activate and deactivate events fire once each fade finishes.

Dark previewReplay preview

Playground

Every knob on one panel. Type and color use Toggle Group, strength uses Slider Ruler, and the button drives the fade.

Dark previewReplay preview
Type
Color
Strength
Strength0.7
Build anything...
<BorderBeam size="md" color-variant="colorful" :strength="0.7">

API Reference

BorderBeam

PropTypeDefaultDescription
size"md" | "sm" | "line" | "pulse-inner" | "pulse-outside""md"Type preset. The first three travel a beam around the border; the pulse pair breathes in place.
colorVariant"colorful" | "mono" | "ocean" | "sunset""colorful"Color palette. mono implies staticColors.
theme"auto" | "dark" | "light""auto"Substrate adaptation. auto resolves from an ancestor data-theme or dark/light class, then from prefers-color-scheme.
strengthnumber1Overall intensity from 0 to 1. Affects only the beam layers.
durationnumber1.96 / 3.1 / 2.3Cycle duration in seconds. The default depends on the type: rotate, line, then pulse.
activebooleantrueWhether the animation is playing. Changes fade.
borderRadiusnumberauto detectedRadius in px. Detected from the first child when omitted, falling back to the preset.
brightnessnumber1.3Glow brightness multiplier.
saturationnumberper presetGlow saturation multiplier.
hueRangenumber30Hue rotation range in degrees. Clamped to 13 for the line type.
staticColorsbooleanfalseDisable the hue-shift animation.
classstringMerged onto the wrapper element.
EventDescription
activateEmitted once the fade-in finishes.
deactivateEmitted once the fade-out finishes.
SlotDescription
defaultThe wrapped content. The first child element supplies the detected border radius.

Accessibility

Keyboard shortcuts and ARIA behavior.

  • Every effect layer is decorative and set to pointer-events: none, so the beam never blocks clicks, focus or screen readers.
  • The pulse types ship a prefers-reduced-motion: reduce block that stops their breathing, and the shared driver skips registering an instance when that preference is set.
  • Each instance pauses its painting when scrolled offscreen (IntersectionObserver with a 256px margin) and resumes on the way back in, without firing activate or deactivate.
  • The pulse breathing runs on one shared requestAnimationFrame loop capped near 30fps rather than a per-instance loop, so many beams on a page stay cheap.