border_beam_flutter
Animated border beam effect for Flutter. A lightweight widget that adds a traveling or breathing glow animation around any element — cards, buttons, inputs, or search bars.
A Flutter port of the border-beam React package by Jakub Antalik, with pixel-level parity of its gradients, masks, and motion.
Install
dependencies:
border_beam_flutter: ^1.0.0
Quick start
import 'package:border_beam_flutter/border_beam_flutter.dart';
BorderBeam(
child: Container(
padding: const EdgeInsets.all(32),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: const Color(0xFF1D1D1D),
),
child: const Text('Your content here'),
),
)
The widget wraps your content and overlays the animated beam effect. Pass
borderRadius matching your child's radius (there is no DOM to auto-detect it
from; it falls back to the size preset default).
Types
Built-in presets control the glow style and motion. They fall into two families:
Rotate (traveling beam)
BorderBeam(size: BorderBeamSize.md, child: card) // Full border glow (default)
BorderBeam(size: BorderBeamSize.sm, child: iconButton) // Compact glow for small elements
BorderBeam(size: BorderBeamSize.line, child: searchBar) // Bottom-only traveling glow
Pulse (breathing glow, no rotation)
BorderBeam(size: BorderBeamSize.pulseInner, child: card) // Contained breathing border glow
BorderBeam(size: BorderBeamSize.pulseOutside, child: card) // Outward-blooming halo
pulseOutsiderequires an opaque wrapped child. The colorful core and halo render behind your content and bloom outward, so only the part that spills beyond the element shows. Make sure the surrounding layout has room for the halo to spill (the effect does not clip).
pulseOutsiderelies on the wrapped element's own 1px border as the idle hairline. If your child has no border, add a subtle 1px border so the edge stays defined while the beam is faded out.
Color variants
BorderBeam(colorVariant: BorderBeamColorVariant.colorful, child: c) // Rainbow (default)
BorderBeam(colorVariant: BorderBeamColorVariant.mono, child: c) // Grayscale
BorderBeam(colorVariant: BorderBeamColorVariant.ocean, child: c) // Blue-purple tones
BorderBeam(colorVariant: BorderBeamColorVariant.sunset, child: c) // Orange-yellow-red tones
All variants except mono animate through a hue-shift cycle.
Theme
BorderBeam(theme: BorderBeamTheme.dark, child: c) // Dark background (default)
BorderBeam(theme: BorderBeamTheme.light, child: c) // Light background
BorderBeam(theme: BorderBeamTheme.auto, child: c) // Follows platform brightness
Strength
BorderBeam(strength: 0.7, child: c) // 70% intensity, child unaffected
Play / pause
BorderBeam(
active: active,
onDeactivate: () => debugPrint('faded out'),
child: c,
)
Toggling active fades the effect in (0.6s) and out (0.5s); the ticker stops
entirely once faded out.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
child |
Widget |
— | Content to wrap |
size |
BorderBeamSize |
md |
Size/type preset |
colorVariant |
BorderBeamColorVariant |
colorful |
Color palette |
theme |
BorderBeamTheme |
dark |
Background adaptation |
strength |
double |
1 |
Effect opacity (0–1), beam layers only |
duration |
double? |
1.96 / 3.1 / 2.3 |
Cycle duration in seconds (rotate / line / pulse) |
active |
bool |
true |
Whether the animation is playing |
borderRadius |
double? |
preset | Border radius in logical px |
brightness |
double? |
per-type | Glow brightness multiplier |
saturation |
double? |
per-theme | Glow saturation multiplier |
hueRange |
double |
30 |
Hue rotation range in degrees |
staticColors |
bool |
false |
Disable the hue-shift animation |
onActivate |
VoidCallback? |
— | Called when fade-in completes |
onDeactivate |
VoidCallback? |
— | Called when fade-out completes |
Pulse tuning hooks (parity with the CSS custom-property hooks):
strokeOpacityFactor, innerOpacityFactor, bloomOpacityFactor,
glowBoost, coreBlur, bloomBlur, glowBrightness, glowSaturation,
hueBase.
Performance
Designed to be cheap enough for always-on ambient use on mobile:
- The pulse breathing is driven at a capped ~30fps — the motion is slow, so halving the paint frequency is imperceptible.
- The heavy blurred bloom layers are frozen at the breathing time-average
and painted once into a cached raster; only a cheap hue-rotate
ColorFiltervaries per frame. - The wrapped child lives in its own
RepaintBoundaryand never repaints because of the effect; the effect layers likewise never invalidate the child. - All tickers stop while
activeis false (after the fade-out completes), and respectTickerMode. - The pulse types honor the platform's reduce-motion setting
(
MediaQuery.disableAnimations), matching the web version'sprefers-reduced-motionbehavior.
Platform support
iOS, Android, macOS, Windows, Linux (Impeller/Skia). Flutter Web is not
supported — its renderer mishandles the saveLayer blend-mode masking the
rotate/line types rely on.
Accessibility
The effect layers are purely decorative and wrapped in IgnorePointer, so
they never interfere with hit-testing or semantics.
Credits
Ported from border-beam by Jakub Antalik — thanks for the original design (live demo).
License
MIT, original copyright retained.
Libraries
- border_beam_flutter
- Animated border beam effect for Flutter — a lightweight widget that adds a traveling or breathing glow animation around any element.