Vanilla Breeze

data-effect

Unified declarative visual effects via the data-effect attribute. Text styling, motion, backgrounds, and display effects.

Unified Effect System

The data-effect attribute is the single entry point for all visual effects in Vanilla Breeze. Instead of separate data-blink, data-glitch, data-shimmer attributes, every effect is activated through one unified attribute.

Scroll-trigger gallery: for every entrance-slot effect (fade-in, slide-up, slide-in, pop, blur-reveal, reveal, scramble, typewriter) fired under data-trigger="scroll", see the scroll-effect gallery. For continuous scroll-linked variants, see data-trigger="view-progress".

How it works

ConceptAttribute / MechanismExample
Effect namedata-effect="name"data-effect="glitch"
Activation triggerdata-triggerdata-trigger="scroll", data-trigger="hover"
Variants & modifiersclassclass="slow", class="line", class="red animate"
Fine-tuningCSS custom properties via stylestyle="--vb-reveal-delay: 120ms"

Multiple effects

Apply multiple effects to a single element with space-separated values:

Composition: animation slots

Try it: the Effects Lab is an interactive composer — toggle effects across slots, swap class modifiers, and watch the generated HTML + composed animation property update live.

Every animated effect publishes into one of four animation slots. A single composer rule on [data-effect] reads all four into a comma-separated animation shorthand, so cross-category pairs compose automatically:

SlotExamplesLifecycle
entrancefade-in, slide-up, pop, slide-in, shadowOne-shot, forwards. Fires once on activation.
attentionshake, pulse, bounce, blinkRepeating, attention-grabbing.
decorationneon, outline.glow, text-3d.animate, rainbow, gradient-text.animate, shimmer, glow, floatContinuous / infinite. Static paint survives loss of the slot.
exitfade-out, collapse, slide-outOne-shot, forwards.

Cross-slot composition is automatic

Effects in different slots compose with no extra work — they each occupy their own animation, so neither steals from the other:

Intra-slot collisions

Two effects in the same slot share one animation. A small number of pairs ship pre-merged keyframes (e.g. fade-in + slide-up, shimmer + gradient-text). For ad-hoc combinations the second selector wins by source order — pick one, or write your own composite selector. Effects that paint static visuals outside the animation (hard-shadow, text-3d without .animate, outline without .glow, stamp) never collide.

Static paint survives slot loss

Decoration effects (neon, outline.glow, text-3d.animate, rainbow) keep their visual when the slot is occupied by something else (e.g. by a custom user animation). The pulse stops, the glow stays — only the motion is lost, not the paint.

Semantic conflicts (cross-slot)

The slot system guarantees that two effects in different slots will both run — animation timelines never clobber each other. It does not guarantee they'll look harmonious. When two effects target the same CSS property, the later slot wins per frame (slot order is entrance → attention → decoration → exit). When one effect's animation makes the element invisible, decorations underneath have nothing to show during that interval. These are intentional limits, not bugs.

ConflictEffects involvedWhat you'll see
Opacity flicker hides decoration blink + neon, blink + shimmer, blink + rainbow, etc. blink drives opacity 1 ↔ 0 with steps(1). The decoration keeps animating, but you only see it during blink's "on" half. Net effect: blinking decoration, which is often not what was intended.
Exit erases decoration mid-flight fade-out + decoration, collapse + decoration, slide-out + decoration Exit animations drop opacity (or max-block-size) to 0 with forwards. Any decoration still running gets carried to invisible along with the element.
Attention transform wins during entrance pop + bounce, slide-up + shake, slide-in + pulse Both slots animate transform. Attention is later in slot order, so it overrides the entrance's transform from frame zero — the entrance scale/translate is suppressed and the attention motion is what you see. The entrance's opacity animation still runs cleanly because attention doesn't touch opacity.
Decoration transform wins after entrance pop + float, slide-up + float Same pattern as above for the entrance phase. Once the entrance ends (forwards snaps to its final transform), the decoration's continuous transform takes over — usually the desired outcome.
Background-clip stack collides shimmer + gradient-text, shimmer + marquee Both effects own the background-image + -webkit-background-clip: text stack. We ship a merged keyframe for shimmer + gradient-text; arbitrary pairs need a bespoke selector.

Workarounds:

  • Pick one effect per perceptual axis. "Make it flash" and "make it shimmer" answer the same question two ways. Choose the one that fits the message.
  • Sequence with the lifecycle hooks. Use VB.onPhaseEnd(el, 'entrance', …) to add an attention or decoration class only after the entrance finishes — see the Lifecycle JS API.
  • Write a bespoke composite selector that merges the two effects' declarations into a single coherent CSS rule — that's how fade-in + slide-up and shimmer + gradient-text are handled in the framework.

Lifecycle JS API

The slot system is paired with a small JS surface for cross-effect coordination:

MethodSignatureUse
VB.activate(el)(el) => voidAdd data-effect-active and fire entrance/attention. Programmatic trigger.
VB.deactivate(el)(el) => voidRemove data-effect-active; slot vars un-publish, animations stop.
VB.onPhaseEnd(el, phase, fn)(el, phase, fn) => unsubscribeRun fn when any keyframe in phase finishes (entrance/exit fire once; finite attention also fires).
VB.registerKeyframe(name, phase)(name, phase) => voidMap a custom keyframe to a phase so animationend classification works for it.
EventFired onDetail
vb:effect-phase-endElement with [data-effect]{ phase, animationName } — phase is entrance | exit | attention | decoration.
vb:phase-changeElement when activated/deactivated{ active: true | false }.
vb:vt-update-doneElements with [data-trigger~="vt"]Fired by VB.swap() after the view transition's updateCallbackDone resolves.

data-effect="blur-reveal" effects

Words start blurred and transition to clear instead of sliding up. Creates a dreamy, focus-pull effect. Triggers on scroll.

Attribute / ClassValuesDescription
data-effect="blur-reveal"Enables the blur reveal effect. Use with data-trigger="scroll".
class="word"Word-by-word split mode (default).
class="line"Line-by-line split mode.
CSS PropertyDefaultDescription
--vb-blur-reveal-delay80msStagger delay between chunks.

data-effect="bounce"

Continuous vertical bounce animation. The element bounces up and down in a rhythmic loop. The kawaii pack overrides this with a spring-loaded hover-only variant when loaded.

Attribute / ClassValuesDescription
data-effect="bounce"Enables the bounce animation (continuous loop).
class="slow"Slower bounce cycle.
class="fast"Faster bounce cycle.
CSS PropertyDefaultDescription
--vb-bounce-height12pxMaximum bounce height.
--vb-duration1sDuration of one bounce cycle.

data-effect="collapse"

Height-to-zero exit animation. The element collapses vertically while fading out, then stays hidden. Useful for dismissible alerts, list item removal, or accordion-style closing.

Attribute / ClassValuesDescription
data-effect="collapse"Enables the collapse exit effect. Activates when data-effect-active is set.
data-trigger="click"Collapse on click.
data-trigger="time:n"Collapse after n milliseconds.
class="slow"Slower collapse duration.
CSS PropertyDefaultDescription
--vb-collapse-height500pxStarting max-height. Set to the element's natural height for a smoother animation.
--vb-duration300msDuration of the collapse animation.

data-effect="fade-in"

Simple opacity fade entrance. Element transitions from transparent to fully visible. Commonly used with data-trigger="scroll" for scroll-triggered reveals.

Attribute / ClassValuesDescription
data-effect="fade-in"Enables the fade-in effect. Use with data-trigger="scroll".
class="slow"Slower fade duration.
class="fast"Faster fade duration.
CSS PropertyDefaultDescription
--vb-fade-in-duration0.6sDuration of the fade animation.

data-effect="fade-out"

Opacity fade exit. Element transitions from visible to transparent. Use with data-trigger="click" or data-trigger="time:n".

Attribute / ClassValuesDescription
data-effect="fade-out"Enables the fade-out effect. Use with data-trigger="scroll".
CSS PropertyDefaultDescription
--vb-fade-out-duration0.6sDuration of the fade-out animation.

data-effect="flipboard" core

Split-flap departure board effect. Each character sits in a dark cell with a horizontal hinge and cycles through random letters before settling on the target. Requires JS.

Attribute / ClassValuesDescription
data-effect="flipboard"Enables the split-flap effect on the element's text content.
CSS PropertyDefaultDescription
--vb-flip-ms60msDuration of each character flip animation.

data-effect="float"

Gentle vertical floating animation. The element bobs up and down in a smooth loop, creating a weightless or hovering appearance.

Attribute / ClassValuesDescription
data-effect="float"Enables the floating animation.
class="slow"Slower float cycle.
class="fast"Faster float cycle.
CSS PropertyDefaultDescription
--vb-float-duration3sDuration of one float cycle.
--vb-float-distance10pxVertical distance of the float movement.

data-effect="glitch" effects

Chromatic aberration glitch with cyan/red channel splitting via CSS pseudo-elements. Tiny JS sets a data-glitch-text attribute for the pseudo-element content.

Attribute / ClassValuesDescription
data-effect="glitch"Enables the glitch effect (always-on by default).
data-trigger="hover"Glitch only on hover.

data-effect="gradient-text"

CSS-only gradient coloring with theme-aware defaults and preset palettes. Add class="animate" for a flowing animation.

Attribute / ClassValuesDescription
data-effect="gradient-text"Enables gradient text. Empty uses theme primary→secondary.
class="sunset"Warm sunset gradient palette.
class="ocean"Cool ocean gradient palette.
class="forest"Deep forest gradient palette.
class="neon"Electric neon gradient palette.
class="animate"Enable flowing gradient animation.

data-effect="glow"

Pulsing drop-shadow glow that alternates between a subtle and intense luminance. Uses filter: drop-shadow() with color-mix() for smooth color transitions. Defaults to the theme's primary color.

Attribute / ClassValuesDescription
data-effect="glow"Enables the pulsing glow animation (2s default cycle).
class="slow"Slower glow pulse.
class="fast"Faster glow pulse.
CSS PropertyDefaultDescription
--vb-glow-colorvar(--color-primary)Glow color. Any CSS color value.
--vb-duration2sDuration of one glow pulse cycle.

data-effect="hard-shadow" core

Hard-edged offset text shadows with no blur. Choose single, double, or long trailing shadows with optional color presets. Sets font-weight: 900.

Attribute / ClassValuesDescription
data-effect="hard-shadow"Enables the hard shadow effect (single shadow default).
class="double"Double shadow style.
class="long"Long trailing shadow style.
class="red", "blue", "gold", "green"Shadow color preset. Combine with style classes.
CSS PropertyDefaultDescription
--vb-shadow-coloroklch(20% 0 0)Shadow color.
--vb-shadow-offset3pxBase shadow offset distance.

data-effect="highlight"

Animated underline, box fill, or circle highlight that draws in when scrolled into view.

Attribute / ClassValuesDescription
data-effect="highlight"Enables the highlight effect. Use with data-trigger="scroll". Default style is underline.
class="underline"Underline highlight style (default).
class="box"Background fill highlight style.
class="circle"Circle highlight style.
CSS PropertyDefaultDescription
--vb-highlight-colorcurrentColorOverride the highlight color.

data-effect="marquee" core

Continuously scrolling horizontal content with edge masking. Children animate left (or right with class="reverse") in an infinite loop.

Attribute / ClassValuesDescription
data-effect="marquee"Enables the marquee scroll effect.
class="reverse"Scroll direction reversed (right-to-left becomes left-to-right).
class="slow"Slow scroll speed (40s cycle).
class="fast"Fast scroll speed (8s cycle).
class="pause"Paused state.
class="hover-pause"Pause animation on hover.
CSS PropertyDefaultDescription
--vb-marquee-speed20sScroll animation duration.
--vb-marquee-gapvar(--size-xl, 3rem)Gap between repeating items.

data-effect="neon" core

Glowing neon text with a pulsing text-shadow halo that breathes in and out over 2.5 seconds.

Attribute / ClassValuesDescription
data-effect="neon"Enables the neon glow effect. Empty uses theme primary.
class="pink"Pink neon color.
class="cyan"Cyan neon color.
class="green"Green neon color.
class="amber"Amber neon color.
class="red"Red neon color.
CSS PropertyDefaultDescription
--vb-neon-colorPer presetThe glow color in OKLCH.
--vb-neon-spread0.04emGlow blur radius.

data-effect="outline" core

Hollow outlined text with transparent fill using -webkit-text-stroke. Gracefully skipped via @supports.

Attribute / ClassValuesDescription
data-effect="outline"Enables the outline text effect (1px default).
class="thick"Thick stroke (2px).
class="ultra"Ultra thick stroke (3px).
class="glow"Glowing outline mode.
CSS PropertyDefaultDescription
--vb-outline-width1pxStroke width.
--vb-outline-colorvar(--color-text)Stroke color.

data-effect="particles" kawaii

JS-driven floating particle effect. Spawns emoji characters (✦ ✧ ⋆ ♡ ☆) that float upward and fade out. Requires JS.

Attribute / ClassValuesDescription
data-effect="particles"Enables floating particle spawning.

data-effect="pop"

Quick scale-up pop animation. The element rapidly scales from small to full size with a slight overshoot, creating a punchy entrance or interaction response.

Attribute / ClassValuesDescription
data-effect="pop"Enables the pop effect.
data-trigger="hover"Pop on hover.
data-trigger="scroll"Pop when scrolled into view.
CSS PropertyDefaultDescription
--vb-pop-scale1.15Maximum scale overshoot.
--vb-pop-duration0.3sDuration of the pop animation.

data-effect="pulse"

Rhythmic scale pulse that grows and shrinks in a continuous loop. Useful for drawing attention to call-to-action elements.

Attribute / ClassValuesDescription
data-effect="pulse"Enables the pulse animation (2s default cycle).
class="slow"Slow pulse (3s cycle).
class="fast"Fast pulse (1s cycle).
CSS PropertyDefaultDescription
--vb-pulse-duration2sDuration of one pulse cycle.
--vb-pulse-scale1.05Maximum scale of the pulse.

data-effect="rainbow" core

Continuous hue-rotation filter that cycles through the full color spectrum.

Attribute / ClassValuesDescription
data-effect="rainbow"Enables rainbow cycling (4s default).
class="slow"Slow cycle (8s).
class="fast"Fast cycle (1.5s).
CSS PropertyDefaultDescription
--vb-rainbow-speed4sDuration of one full hue cycle.

data-effect="reveal"

Word-by-word or line-by-line entrance animation. Text slides up and fades in with staggered timing when scrolled into view.

Attribute / ClassValuesDescription
data-effect="reveal"Enables the reveal effect. Use with data-trigger="scroll".
class="word"Word-by-word split mode (default).
class="line"Line-by-line split mode.
CSS PropertyDefaultDescription
--vb-reveal-delay80msStagger delay between chunks.
--vb-reveal-duration400msAnimation duration per chunk.

data-effect="scramble" effects

Characters resolve left-to-right from random symbols. Think Hollywood decryption or sci-fi terminal output. Triggers on scroll.

Attribute / ClassValuesDescription
data-effect="scramble"Enables the scramble effect. Use with data-trigger="scroll".
CSS PropertyDefaultDescription
--vb-scramble-duration1.5sTotal scramble duration.
--vb-scramble-chars!<>-_\\/[]{}=+*^?#Character set for random characters.
--vb-scramble-speed30msFrame interval.

data-effect="shadow"

Elevated box-shadow decoration with a subtle lift animation. The element rises slightly and gains depth, transitioning from a light shadow to a more pronounced elevated shadow. Ideal for cards, panels, and call-to-action containers.

Attribute / ClassValuesDescription
data-effect="shadow"Enables the shadow lift effect.
data-trigger="scroll"Lift when scrolled into view.
class="slow"Slower lift duration.
CSS PropertyDefaultDescription
--vb-shadow0 8px 24px oklch(0% 0 0 / 0.18)Final elevated box-shadow. Override for branded shadows.
--vb-duration400msDuration of the lift animation.

data-effect="shake"

Rapid horizontal shaking animation. Useful for error states, attention-grabbing, or playful interactions. Runs continuously or on hover.

Attribute / ClassValuesDescription
data-effect="shake"Enables the shake effect (continuous by default).
data-trigger="hover"Shake only on hover.
CSS PropertyDefaultDescription
--vb-shake-intensity4pxHorizontal displacement distance.
--vb-shake-duration0.4sDuration of one shake cycle.

data-effect="shimmer"

CSS-only shimmering highlight that sweeps across the text on a loop.

Attribute / ClassValuesDescription
data-effect="shimmer"Enables the shimmer effect (2s default cycle).
class="slow"Slow shimmer speed.
class="fast"Fast shimmer speed.

data-effect="slide-in"

Horizontal entrance animation that respects text direction. In LTR, the element slides in from the left; in RTL, from the right. Uses :where([dir="rtl"]) for automatic direction support.

Attribute / ClassValuesDescription
data-effect="slide-in"Enables horizontal entrance. Use with data-trigger="scroll".
class="slow"Slower slide duration.
class="fast"Faster slide duration.
CSS PropertyDefaultDescription
--vb-slide-distance40pxHorizontal offset distance.
--vb-duration400msDuration of the slide animation.

data-effect="slide-out"

Horizontal exit animation. The element slides out in the inline-end direction while fading. Mirrors slide-in with reversed direction and RTL support via :where([dir="rtl"]).

Attribute / ClassValuesDescription
data-effect="slide-out"Enables horizontal exit. Activates when data-effect-active is set.
data-trigger="click"Slide out on click.
class="slow"Slower slide duration.
CSS PropertyDefaultDescription
--vb-slide-distance40pxHorizontal offset distance.
--vb-duration400msDuration of the slide animation.

data-effect="slide-up"

Element slides upward into its final position while fading in. A clean, modern entrance animation commonly paired with scroll triggering.

Attribute / ClassValuesDescription
data-effect="slide-up"Enables the slide-up entrance. Use with data-trigger="scroll".
class="slow"Slower slide duration.
class="fast"Faster slide duration.
CSS PropertyDefaultDescription
--vb-slide-up-distance20pxStarting offset distance below final position.
--vb-slide-up-duration0.6sDuration of the slide animation.

data-effect="sparkle" kawaii

CSS-only floating sparkle stars. Two ✦ characters orbit the element with staggered float animations — one gold at top-right, one lavender at bottom-left.

Attribute / ClassValuesDescription
data-effect="sparkle"Adds floating sparkle stars via pseudo-elements.

data-effect="stamp" core

Rubber stamp effect with fractal noise SVG filter, rotation, and mix-blend-mode: multiply. Requires JS for the SVG filter injection.

Attribute / ClassValuesDescription
data-effect="stamp"Enables the stamp effect. Empty defaults to red ink.
class="red", "blue", "green", "black", "gold"Ink color preset.
class="straight"No rotation (0deg).
class="slight"Slight rotation (-2deg).
class="heavy"Heavy rotation (-8deg).
CSS PropertyDefaultDescription
--vb-stamp-colorPer presetInk color in OKLCH.

data-effect="starburst" kawaii

Animated pastel starburst gradient background with rotating 10-degree conic-gradient rays and soft radial bokeh at the bottom.

Attribute / ClassValuesDescription
data-effect="starburst"Enables the animated starburst background.

data-effect="text-3d" core

Bold text with layered drop-shadows creating a 3D extrusion effect. Sets font-weight: 900.

Attribute / ClassValuesDescription
data-effect="text-3d"Enables the 3D extrusion effect.
class="red", "gold", "green", "purple", "black"Shadow color preset.
class="deep"Doubles shadow angle to 2px for deeper extrusion.
class="animate"Oscillates shadow direction over 3 seconds.
CSS PropertyDefaultDescription
--vb-3d-colorPer presetExtrusion color in OKLCH.
--vb-3d-angle1pxShadow offset per layer.

data-effect="typewriter" effects

Classic character-by-character typing with optional blinking cursor and looping. Triggers when scrolled into view.

Attribute / ClassValuesDescription
data-effect="typewriter"Enables the typewriter effect. Use with data-trigger="scroll".
class="loop"Loop the typing animation.
class="no-cursor"Hide the blinking cursor.
CSS PropertyDefaultDescription
--vb-typewriter-speed50msTyping speed per character.
--vb-typewriter-delay0msInitial delay before typing starts.

data-effect="wiggle" kawaii

Playful left-right rotation wobble. Runs continuously by default, or only on hover.

Attribute / ClassValuesDescription
data-effect="wiggle"Enables the wiggle effect (continuous by default).
data-trigger="hover"Wiggle only on hover.

data-effect="ticker" effects

Animated number count-up on <data> elements. Counts from a start value to the element's value attribute using easeOutExpo easing — fast start, decelerating finish. Pairs with data-format-number for locale-aware formatting during animation.

Attributes

AttributeValuesDescription
data-effect="ticker"Enables animated count-up. Use on <data> elements with a value attribute.
data-trigger="scroll"Start animation when scrolled into view (IntersectionObserver, 10% threshold).
data-format-numbercurrency, percent, compactApply Intl.NumberFormat to intermediate values during animation.
data-currencye.g. USD, EURCurrency code when using data-format-number="currency".
data-localee.g. de-DEOverride locale for this element (defaults to html[lang]).

CSS Properties

CSS PropertyDefaultDescription
--vb-ticker-duration1000Animation duration in ms.
--vb-ticker-start0Starting number for count-up.
--vb-ticker-decimalsautoDecimal places (auto-detected from value if omitted).

How It Works

  1. The scroll trigger watches for the element to enter the viewport (10% threshold)
  2. A requestAnimationFrame loop animates from start to end value at 60fps
  3. Each frame applies easeOutExpo easing for a fast-start, decelerating finish
  4. Intermediate values are formatted with Intl.NumberFormat matching any data-format-number options
  5. At completion, sets data-format-number-init to prevent double-formatting

With Format Number

Combine with data-format-number for locale-aware formatting during the animation:

Stats Pattern

The ticker pairs naturally with the Stats pattern:

Reduced Motion

The ticker checks prefers-reduced-motion: reduce and :root[data-motion-reduced]. When either is true, the animation is skipped entirely — the original text content is preserved as-is. data-format-number still formats normally.

Easing

See also: data element for byte formatting and locale overrides.

Shared Behavior

Progressive Enhancement

All effects are progressive enhancements. Text is fully readable without JavaScript. CSS-only effects need no JS at all. Effects without a pack badge are in core.

Reduced Motion

All effects respect prefers-reduced-motion: reduce and :root[data-motion-reduced]. When reduced motion is active, text displays immediately with no animation.

Screen Readers

JS effects that split text into spans set aria-label on the host element so screen readers announce the full text naturally.

Scroll Trigger

Effects with data-trigger="scroll" use IntersectionObserver with threshold: 0.1 to trigger when scrolled into view. Effects play once (except data-effect="typewriter" with class="loop").

Dynamic Elements

A MutationObserver watches for dynamically added elements, so effects work with client-side rendering and lazy loading.

CSS Layer

Core effects use @layer web-components. Pack effects use @layer bundle-effects.

Accessibility

  • aria-label preserves full text for screen readers
  • prefers-reduced-motion respected by all effects
  • CSS-only effects degrade gracefully in older browsers via @supports
  • No content is hidden permanently — text is always accessible
  • Guard attributes (data-*-init) prevent double initialization