
Border Beam Vanilla is a Vanilla JavaScript library that decorates DOM elements with animated traveling border glows.
It ports the effect from Jakubantalik’s original border-beam concept to vanilla JS.
Features:
- Adds a moving glow to an existing DOM element.
- Supports small, medium, and line style presets.
- Switches between colorful, mono, ocean, and sunset palettes.
- Adapts the glow for dark, light, and system theme modes.
- Reads the element border radius when you skip a manual value.
- Updates the active instance through a controller object.
- Fades the effect in and out through runtime state control.
- Ships ESM, CJS, and TypeScript definitions.
See It In Action:
Use Cases:
- Highlight a pricing card with a moving border accent.
- Add motion to an icon button in a toolbar.
- Accent a search bar with a bottom edge beam.
- Draw attention to a settings panel or status box.
How to use it:
1. Install Border Beam Vanilla with NPM.
# NPM $ npm install border-beam-vanilla
2. Import attachBorderBeam and target any element on your page.
<div class="feature-card" id="feature-card"> <h3>Motion Layer</h3> <p>Animated focus treatment for modern interfaces.</p> </div>
import { attachBorderBeam } from "border-beam-vanilla";
// OR
import { attachBorderBeam } from "./dist/index.es.js";
// Select the existing element that should receive the beam effect
const featureCard = document.querySelector("#feature-card");
// Attach the beam with a medium preset and an ocean palette
const featureCardBeam = attachBorderBeam(featureCard, {
size: "md",
colorVariant: "ocean",
theme: "dark",
strength: 0.85
});
// Keep the controller if you want to update or destroy the instance later
window.featureCardBeam = featureCardBeam;3. The sm preset fits icon buttons and compact controls.
<button class="icon-action" id="icon-action" type="button">+</button>
// Attach a compact beam to a small action button
attachBorderBeam(document.querySelector("#icon-action"), {
size: "sm",
colorVariant: "sunset",
theme: "dark"
});4. The line preset focuses motion on the bottom edge. It’s great for search bars and command inputs.
<div class="search-shell" id="search-shell">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<span>Search components</span>
</div>// Attach the bottom edge beam to a search style surface
attachBorderBeam(document.querySelector("#search-shell"), {
size: "line",
colorVariant: "colorful",
theme: "dark",
duration: 2.4,
borderRadius: 20
});5. Use createBorderBeam() if you want the package to create the target <div> for you.
// Create a new decorated div
const noticeBeam = createBorderBeam({
size: "md",
colorVariant: "colorful",
theme: "dark"
});
// Add your own content after the element is created
noticeBeam.element.className = "notice-box";
noticeBeam.element.innerHTML = `
<strong>Export Complete</strong>
<p>Your asset bundle is ready for review.</p>
`;
// Insert the generated element into the page
document.body.appendChild(noticeBeam.element);
6. Update, pause, resume, and destroy the effect:// Attach the beam and store the controller
const settingsBeam = attachBorderBeam(document.querySelector("#settings-panel"), {
size: "md",
colorVariant: "colorful",
theme: "dark"
});
// Fade the effect out
settingsBeam.setActive(false);
// Fade the effect back in
settingsBeam.setActive(true);
// Update the active instance with a new palette and lower strength
settingsBeam.update({
colorVariant: "mono",
strength: 0.55
});
// Remove the effect and clean up observers, style tags, and bloom layers
settingsBeam.destroy();7. All configuration options.
size("sm" | "md" | "line"): Selects the beam preset. Default:"md".colorVariant("colorful" | "mono" | "ocean" | "sunset"): Selects the color palette. Default:"colorful".theme("dark" | "light" | "auto"): Selects the surface theme. Default:"dark".staticColors(boolean): Stops hue rotation. Mono mode stays static even if you skip this value. Default:false.duration(number): Sets the animation cycle in seconds. Default:1.96forsmandmd. Default:2.4forline.active(boolean): Starts the instance in the active state. Default:true.borderRadius(number): Sets the border radius in pixels. The runtime reads the computed element radius when you skip this value.brightness(number): Sets the glow brightness multiplier. Default:1.3.saturation(number): Sets the glow saturation multiplier. The runtime uses preset values when you skip this value.hueRange(number): Sets the hue rotation range in degrees. Default:30. Thelinepreset caps the final value at13.strength(number): Sets effect opacity from0to1. Default:1.onActivate(() => void): Runs after the fade in animation completes.onDeactivate(() => void): Runs after the fade out animation completes.
8. API methods.
import {
attachBorderBeam,
createBorderBeam,
resolveSystemTheme,
resolveBorderBeamOptions,
resolveTheme,
detectBorderRadius
} from "border-beam-vanilla";
// Attach the beam to an existing DOM element
const toolbarBeam = attachBorderBeam(document.querySelector("#toolbar"), {
size: "sm",
colorVariant: "sunset",
theme: "dark"
});
// Update the current instance with a new config object
toolbarBeam.update({
colorVariant: "ocean",
strength: 0.7
});
// Toggle the current instance state
toolbarBeam.setActive(false);
toolbarBeam.setActive(true);
// Remove the current instance from the element
toolbarBeam.destroy();
// Create a new decorated div and return the controller plus the element
const bannerBeam = createBorderBeam({
size: "md",
colorVariant: "colorful"
});
document.body.appendChild(bannerBeam.element);
// Read the current system theme from matchMedia
const systemTheme = resolveSystemTheme();
// Resolve a theme value from the input theme and the system fallback
const themeValue = resolveTheme("auto", systemTheme);
// Read the numeric border radius from an element
const detectedRadius = detectBorderRadius(document.querySelector("#toolbar"));
// Resolve the final runtime options for an element and config object
const resolvedOptions = resolveBorderBeamOptions(document.querySelector("#toolbar"), {
size: "line",
theme: "auto"
});
console.log(systemTheme, themeValue, detectedRadius, resolvedOptions);FAQs:
Q: Does border-beam-vanilla need React or another framework?
A: No. The API works on plain HTMLElement values. You can call it from any stack that exposes DOM access.
Q: Why does the beam not show up in one browser?
A: The effect depends on modern CSS features such as @property, conic gradients, and mask composition. Target current Chrome, Safari, and Firefox releases.
Q: How do I stop the beam on an inactive panel?
A: Keep the controller from attachBorderBeam(). Call setActive(false) when the panel loses focus or leaves view.
Q: Can I keep the radius from my own CSS?
A: Yes. Skip borderRadius and let the runtime read the computed value. Pass a number if you need a fixed radius.







