Advanced Configuration

StringTune ships with sensible defaults, but you can tailor scroll behaviour, module fallbacks, and runtime tuning through a small set of APIs. This guide documents the configuration surface that exists in the current build.


Global Defaults with setupSettings

Call stringTune.setupSettings() once before starting the engine to provide fallback values that every module can reference. Attribute values in the DOM still win, so this is ideal for theming, spacing presets, or mobile tweaks.

import StringTune from '@fiddle-digital/string-tune';

const stringTune = StringTune.getInstance();

stringTune.setupSettings({
  'offset-top': '-10%',
  'offset-bottom': '-10%',
  parallax: 0.25,
  lerp: 0.8,
  glide: 0.75,
  repeat: 'true',
});

stringTune.start(60);

Layout & Activation Keys

KeyDefaultModulesPurposeExample
active'false'All modulesOpt-in toggle without removing the element from the DOM.string-active="true"
fixed'false'Scroll/ProgressLock an object in place while it remains active.string-fixed="true"
outside-container'false'Progress, Cursor trackersTreat measurements as if the object lived outside the scroll root.string-outside-container="true"
repeat'false'Progress, Lazy, Autoplay, FormAllow triggers to fire again after exit.string-repeat="true"
self-disable'false'All modulesPermanently disable the object after its first activation.string-self-disable="true"
abs'false'Layout-sensitive modulesInterpret positions in absolute (page) space.string-abs="true"
global-classfalseScroll engineToggle directional helper classes (is-scroll-forward, etc.) on <html>.stringTune.setupSettings({ 'global-class': true });

Viewport Timing Keys

KeyDefaultModulesPurposeExample
offset-top'0%'Progress family, ParallaxStart reacting before the element hits the viewport.string-offset-top="-25%"
offset-bottom'0%'Progress family, ParallaxExtend progression beyond the element's bottom edge.string-offset-bottom="12vh"
inview-top'0%'Inview-aware modulesAdjust enter threshold.string-inview-top="18%"
inview-bottom'0%'Inview-aware modulesAdjust exit threshold.string-inview-bottom="-30%"
enter-el'top'Progress familyDefine the element edge that should be matched against the viewport.string-enter-el="bottom"
exit-el'bottom'Progress familySelect the viewport edge used for comparisons.string-exit-el="top"
enter-vp'bottom'Progress familyDefine the element edge that should be matched against the viewport.string-enter-vp="top"
exit-vp'top'Progress familySelect the viewport edge used for comparisons.string-exit-vp="bottom"

Scroll & Motion Keys

KeyDefaultModulesPurposeExample
key'--progress'ProgressCSS custom property used when none is provided per element.string-key="--hero-progress"
easing'cubic-bezier(0.25, 0.25, 0.25, 0.25)'Progress, ParallaxShape the progress curve without rewriting markup.string-easing="cubic-bezier(0.4, 0, 0.2, 1)"
parallax'0.2'ParallaxBase strength for depth offsets.string-parallax="0.35"
parallax-bias'0.0'ParallaxBias entry vs exit travel.string-parallax-bias="0.25"
glide'1'GlideBase multiplier for scroll-driven drift.string-glide="0.6"
anchor'center center'AnchorDefault transform-origin when none is supplied.string-anchor="top center"

Cursor, Magnetic & Spotlight Keys

KeyDefaultModulesPurposeExample
lerp'0.15'Cursor, Spotlight, MagneticPointer smoothing factor (remapped internally to 0.05–0.65 range).string-lerp="0.45"
cursor-lerp'0.1'Global Cursor (Controller)Global cursor smoothing (for cursor portals).cursor-lerp="0.2"
alignment'center'CursorNormalize coordinates: center (-1…1), start/end (0…1).string-alignment="start"
target-disable'false'CursorOpt element out of cursor interactions.string-target-disable="true"
target-style-disable'false'CursorSkip writing --x/--y CSS variables to target.string-target-style-disable="true"
cursor-target'default'CursorID(s) of cursor portal(s) to target (comma/pipe-separated, or *).string-cursor-target="cta,special"
target-class''CursorClass added to the target element itself while hovered.string-target-class="is-hovered"
cursor-class''CursorClass added to cursor portal(s) while target is hovered.string-cursor-class="cursor--dark"
strength'0.3'MagneticPull force when the pointer enters the radius.string-strength="0.45"
radius'150'MagneticInteraction radius in pixels.string-radius="240"

Impulse (Physics) Keys

KeyDefaultPurposeExample
position-strength3Scales linear impulse from pointer velocity.string-position-strength="4.5"
position-tension0.05Restoring force towards the origin.stringTune.setupSettings({ 'position-tension': 0.08 });
position-friction0.15Dampens velocity over time.string-position-friction="0.22"
position-max-velocity10Caps translational velocity.string-position-max-velocity="14"
position-update-threshold0.1Minimal displacement before position updates propagate.string-position-update-threshold="0.05"
rotation-strength0.75Angular impulse multiplier.string-rotation-strength="1.2"
rotation-tension0.06Pull-back force for rotation.stringTune.setupSettings({ 'rotation-tension': 0.09 });
rotation-friction0.18Dampens angular velocity.string-rotation-friction="0.25"
rotation-max-angular-velocity6Caps rotational speed.string-rotation-max-angular-velocity="8"
rotation-max-angle18Absolute rotation clamp in degrees.string-rotation-max-angle="22"
rotation-update-threshold0.15Minimal angle change before CSS updates.string-rotation-update-threshold="0.1"
max-offset220Absolute clamp for translation values.string-max-offset="300"
sleep-epsilon0.01Threshold below which physics is considered at rest.stringTune.setupSettings({ 'sleep-epsilon': 0.005 });
continuous-pushtrueAllow repeated impulses while hovered.string-continuous-push="false"

System & Loading Keys

KeyDefaultModulesPurposeExample
timeout900LoadingMilliseconds before the loading overlay auto-hides.string-timeout="1200"

Pass values exactly as you would in HTML attributes ('20%', '4rem', 'true', numeric literals, etc.).


Runtime Tweaks

Scroll Dynamics

PropertyDefaultEffect
stringTune.speed0.1Base smoothing for scroll velocity; smaller values feel heavier
stringTune.speedAccelerate0.3How quickly the engine reacts to sudden deltas; higher is snappier
const stringTune = StringTune.getInstance();
stringTune.speed = 0.14;
stringTune.speedAccelerate = 0.32;

Manual Scroll Control

You rarely need to touch these directly, but they are available for custom scroll syncing.

  • stringTune.scrollPosition = 640; — sets the internal scroll state; the scroll manager will animate to this point.
  • stringTune.scrollTo(position: number) — helper that forwards to the active scroll strategy.
  • stringTune.scrollToElement(selector: string, offset = 0) — convenience wrapper for element targeting.
await nextTick();
stringTune.scrollToElement('#pricing', 120);

Recomputing Layout

  • stringTune.onResize(true) — force a rebuild of measurements, offsets, and responsive settings.
  • stringTune.invalidateCenters() — flush cached element centers; useful after DOM transforms that do not change size.
watch(posts, async () => {
  await nextTick();
  stringTune.onResize(true);
  stringTune.invalidateCenters();
});

There is no generic stringTune.onResize(true) helper in the current build; the resize pipeline above is the intended public entry point.

Teardown

stringTune.destroy() removes listeners, stops the loop, and clears module state. Handy for SPA route unloads or test suites.


Example: Theme + Scroll Preset

import StringTune, { StringParallax, StringMagnetic, StringProgress } from '@fiddle-digital/string-tune';

const stringTune = StringTune.getInstance();

stringTune.setupSettings({
  'offset-top': '-12vh',
  'offset-bottom': '8vh',
  parallax: 0.28,
  lerp: 0.65,
  strength: 0.4,
});

stringTune.use(StringParallax);
stringTune.use(StringMagnetic);
stringTune.use(StringProgress);

stringTune.speed = 0.12;
stringTune.speedAccelerate = 0.35;

stringTune.start(60);

Best Practices

  • Set defaults once: Call setupSettings before the first use() to ensure modules pick up your values during their initial connect.
  • Prefer attributes for exceptions: Keep global defaults broad and override specific cases in markup (string-offset-top="25vh").
  • Rebuild deliberately: Batch DOM updates and call onResize(true) once per frame instead of triggering it repeatedly.
  • Avoid restarting: Use the singleton instance; restarting the engine discards scroll inertia and can feel jarring.
  • Profile tweaks: Small changes to speed or speedAccelerate drastically alter feel—test on both touchpads and wheels.